> typeof undefined 'undefined' > typeof null // well-known bug 'object' > typeof true 'boolean' > typeof 123 'number' > typeof "abc" 'string' > typeof function() {} 'function' > typeof {} 'object' > typeof [] 'object' > typeof unknownVariable 'undefined'typeof null returning "object" is clearly a bug. This will probably be fixed in ECMAScript.next and the return value will then be "null".
instanceof. Use instanceof to determine whether an object is an instance of a given type. instanceof always returns false for primitive values.
> {} instanceof Object true > (function() {}) instanceof Function true > true instanceof Object false
A String value indicating a specification defined classification of objects.There is no way to access this value directly from JavaScript, however Object.prototype.toString() uses it:
> {}.toString() '[object Object]'Object, the second word in the square brackets, comes from [[Class]]. The first word is always object. While toString() is overridden in subclasses of Object, you can apply Object.prototype.toString() generically [2] to get the original functionality back:
> [1,2,3].toString() '1,2,3' > Object.prototype.toString.call([1,2,3]) '[object Array]' > /xyz/.toString() '/xyz/' > Object.prototype.toString.call(/xyz/) '[object RegExp]'The article “Fixing the JavaScript typeof operator” (by Angus Croll) makes use of this fact to define a toType() function that uses a regular expression to extract the value of [[Class]] from between the square brackets.
var toType = function(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() }Usage examples:
toType({a: 4}) // "object" toType([1, 2, 3]) // "array" (function() { return toType(arguments) }()) // "arguments" toType(new ReferenceError()) // "error" toType(new Date()) // "date" toType(/a-z/) // "regexp" toType(Math) // "math" toType(JSON) // "json" toType(new Number(4)) // "number" toType(new String("abc")) // "string" toType(new Boolean(true)) // "boolean"Problems with this approach:
> typeof "abc" 'string' > new String("abc") instanceof String trueThe first string is a primitive, the second is an object. The former starts with a lowercase letter, the latter starts with an uppercase letter.
> {}.toString.call(new ReferenceError()) '[object Error]' > {}.toString.call(new TypeError()) '[object Error]' > {}.toString.call(new Error()) '[object Error]'
if (someValue === Math) { ... }
> Object.prototype.toString.call(123) '[object Number]'
function getTypeName(value) { if (value === null) { return "null"; } var t = typeof value; switch(t) { case "function": case "object": if (value.constructor) { if (value.constructor.name) { return value.constructor.name; } else { // Internet Explorer // Anonymous functions are stringified as follows: 'function () {}' // => the regex below does not match var match = value.constructor.toString().match(/^function (.+)\(.*$/); if (match) { return match[1]; } } } // fallback, for nameless constructors etc. return Object.prototype.toString.call(value).match(/^\[object (.+)\]$/)[1]; default: return t; } }Applied to the arguments that we previously used for toType():
getTypeName({a: 4}) // "Object" getTypeName([1, 2, 3]) // "Array" (function() { return getTypeName(arguments) }()) // "Object" getTypeName(new ReferenceError()) // "ReferenceError" getTypeName(new Date()) // "Date" getTypeName(/a-z/) // "RegExp" getTypeName(Math) // "Object" getTypeName(JSON) // "Object" getTypeName(new Number(4)) // "Number" getTypeName(new String("abc")) // "String" getTypeName(new Boolean(true)) // "Boolean"There is one caveat: You still need to use typeof for unknown variables.
> getTypeName(unknownVariable) ReferenceError: unknownVariable is not defined > typeof unknownVariable 'undefined'Lastly, if the constructor is anonymous, the best either function can do is tell us that an instance is an object:
> var Foo = function () {}; > var foo = new Foo(); > toType(foo) 'object' > getTypeName(foo) 'Object'