retrieve the type of your value by using constructors when possible
Foretaste
when it can, typeof-- retrieves the type of your value by extracting the name of its constructors
var typeOf = ;; // 'Number';
Why use typeof-- ?
typeof and instanceof are, somehow, broken
null
For example, null has a type of an object, but it is not an instance of Object.
typeof null; // 'object'null instanceof Object //false
[fun fact] Object.prototype has the same result as null with typeof and instanceof
RegEx
Using a regular expression literal, someone would expect typeof to return a specific value like "regexp" which would be great in a perfect world.
typeof /regularExpression/ // 'object'/regularExpression/ instanceof RegExp // true
So, if you're dealing with regex, use instanceof.
Primitives x Objects
Unlike RegEx, other values like Number, String or Boolean have some issues when we want to retrieve their type when we use them as primitive or object (wrapper).
typeof 42 //'object' , create an objecttypeof Number42 //'number', create a primitive valuetypeof 42 //'number' 666 instanceof Number //false42 instanceof 666constructor //true, because:666constructor === Numberprototypeconstructor
So, the previous example shows that it is possible to verify a primitive value with typeof and its wrapper with instanceof but we can't test both of them with the same method even if they share the same constructor. One method to deal with this problem would be to use typeof value.valueOf().
NaN
One of the most famous example in JavaScript is NaN (a.K.a "Not a Number") which return a type of: number...
typeof NaN //'number' *sigh*typeof NaN //'object' *sigh* x 2
Prototypes
As you may have noticed above, prototypes have a weird behavior. For example, the prototype of an Array is an empty Array, and it is the same thing with Number, String, Boolean... which store a default value (0,"",false). Therefore, we would expect them to be an instance of their own constructor. But, sadly, it is not the case...
Numberprototype instanceof Number //falseNumberprototype instanceof Numberprototypeconstructor //false //the best method so far to deal with it.ObjectprototypetoString //'[object Number]'
And many more...
Why typeof-- help us:
typeof-- retrieve the constructor name when this one is valid. Otherwise it will call Object.prototype.toString.
String, Number and Boolean return the exact same type whether it's an object or a primitive value.
null, undefined and NaN have their own type (respectively: #Null, #Undefined and #NaN)
An Instance of an anonymous constructor will return #Anonymous instead of an empty string to improve readability.
And finally, the library can deal with built-in object like JSON, Math or prototypes by calling Object.prototype.toString when the type extracted from constructors is equal to "Object".
Usage:
var typeOf = ;{}var {}; ;// 'String'; // 'Number'; // 'Boolean';// 'RegExp'; // '#Null'; // '#Undefined'; // '#NaN'; // 'Array'; // 'Object'; // 'Math'; // '#NaN'; // 'Number'; // 'TypeError'; // 'MyOwnClass';//'#Anonymous' // /!\ be careful with constructors/!\{}var myObject = ; //tEsT, typeof-- is case sensitive //invalid constructors will call Object.prototype.toString!Objectconstructor = myObject{}; //'Object' // and so on ...
force Object.prototype.toString call
you can force the call of Object.prototype.toString by adding 'forceObjectToString'.
// '#NaN' // 'Error' {}; // 'Object' //on Node.JSvar mybuffer = 4;; // 'Buffer'; // 'UInt8Array'
see table below for more example. ([tampered constructors] column)
table of common values
and their type returned by typeOf(value)
See JavaScript reference or HTML API reference for more types.
values | types | tampered constructors |
---|---|---|
42 | 'Number' | 'Number' |
new Number(42) | 'Number' | 'Number' |
'lolipop' | 'String' | 'String' |
new String('lolipop') | 'String' | 'String' |
true | 'Boolean' | 'Boolean' |
new Boolean(true) | 'Boolean' | 'Boolean' |
/myRegExp/ | 'RegExp' | 'RegExp' |
new RegExp(/myRegExp/) | 'RegExp' | 'RegExp' |
null | '#Null' | '#Null' |
undefined | '#Undefined' | '#Undefined' |
NaN | '#NaN' | '#NaN' |
new Number('NaN') | '#NaN' | '#NaN' |
[] | 'Array' | 'Array' |
new Array() | 'Array' | 'Array' |
{} | 'Object' | 'Object' |
new Object() | 'Object' | 'Object' |
new Error() | 'Error' | 'Error' |
new TypeError() | 'TypeError' | 'Error' |
new Map() | 'Map' | 'Map' |
new WeakMap() | 'WeakMap' | 'WeakMap' |
new Date() | 'Date' | 'Date' |
Object | 'Function' | 'Function' |
function(){} | 'Function' | 'Function' |
new (function MyCustomKlass(){})() | 'MyKlass' | 'Object' |
new (function(){})() | '#Anonymous' | 'Object' |
(function(){ return arguments })() | 'Arguments' | 'Arguments' |
Array.prototype | 'Array' | 'Array' |
[global] JSON | 'JSON' | 'JSON' |
[ES6:promise] new Promise(function(){}) | 'Promise' | 'Object' |
[ES6:generator] function*(){} | 'GeneratorFunction' | 'GeneratorFunction' |
[ES6:Symbol] Symbol('foo') | 'Symbol' | 'Symbol' |
[ES6:fat arrow] ()=>{} | 'Function' | 'Function' |
'Arguments' type become 'Object' in [IE6..8]
Be careful with Web APIs, they might return different values depending on your browser version.
Example: typeOf(document) will return [IE6..8] 'Object', [IE9..10] 'Document' or [IE11+] 'HTMLDocument'
with requireJS (AMD)
require;;
you might also be interested with the typeof-in library which use instanceof when needed.
Finally, I'm open to any suggestions.