Better way to get type of a Javascript variable?

Better way to get type of a Javascript variable?

Is there a better way to get the type of a variable in JS than typeof? It works fine when you do:
> typeof 1
“number”
> typeof “hello”
“string”

But it’s useless when you try:
> typeof [1,2]
“object”
>r = new RegExp(/./)
/./
> typeof r
“function”

I know of instanceof, but this requires you to know the type beforehand.
> [1,2] instanceof Array
true
> r instanceof RegExp
true

Is there a better way?

Solutions/Answers:

Solution 1:

Angus Croll recently wrote an interesting blog post about this –

http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

He goes through the pros and cons of the various methods then defines a new method ‘toType’ –

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

Solution 2:

You can try using constructor.name.

[].constructor.name
new RegExp().constructor.name

As with everything JavaScript, someone will eventually invariably point that this is somehow evil, so here is a link to an answer that covers this pretty well.

An alternative is to use Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)

Solution 3:

A reasonably good type capture function is the one used by YUI3:

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

This captures many of the primitives provided by javascript, but you can always add more by modifying the TYPES object. Note that typeof HTMLElementCollection in Safari will report function, but type(HTMLElementCollection) will return object

Solution 4:

You may find the following function useful:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

Or in ES7 (comment if further improvements)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

Results:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

Thanks @johnrees for notifying me of: error, promise, generatorfunction

Related:  Remove Last Comma from a string

Solution 5:

Also we can change a little example from ipr101

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

and call as

"aaa".toType(); // 'string'

Solution 6:

one line function:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

this give the same result as jQuery.type()