The most accurate way to check JS object's type?

后端 未结 9 983
借酒劲吻你
借酒劲吻你 2020-12-04 05:33

The typeof operator doesn\'t really help us to find the real type of an object.

I\'ve already seen the following code :

Object.prototyp         


        
相关标签:
9条回答
  • 2020-12-04 05:42

    the Object.prototype.toString is a good way, but its performance is the worst.

    http://jsperf.com/check-js-type

    check js type performance

    Use typeof to solve some basic problem(String, Number, Boolean...) and use Object.prototype.toString to solve something complex(like Array, Date, RegExp).

    and this is my solution:

    var type = (function(global) {
        var cache = {};
        return function(obj) {
            var key;
            return obj === null ? 'null' // null
                : obj === global ? 'global' // window in browser or global in nodejs
                : (key = typeof obj) !== 'object' ? key // basic: string, boolean, number, undefined, function
                : obj.nodeType ? 'object' // DOM element
                : cache[key = ({}).toString.call(obj)] // cached. date, regexp, error, object, array, math
                || (cache[key] = key.slice(8, -1).toLowerCase()); // get XXXX from [object XXXX], and cache it
        };
    }(this));
    

    use as:

    type(function(){}); // -> "function"
    type([1, 2, 3]); // -> "array"
    type(new Date()); // -> "date"
    type({}); // -> "object"
    
    0 讨论(0)
  • 2020-12-04 05:45

    I'd argue that most of the solutions shown here suffer from being over-engineerd. Probably the most simple way to check if a value is of type [object Object] is to check against the .constructor property of it:

    function isObject (a) { return a != null && a.constructor === Object; }
    

    or even shorter with arrow-functions:

    const isObject = a => a != null && a.constructor === Object;
    

    The a != null part is necessary because one might pass in null or undefined and you cannot extract a constructor property from either of these.

    It works with any object created via:

    • the Object constructor
    • literals {}

    Another neat feature of it, is it's ability to give correct reports for custom classes which make use of Symbol.toStringTag. For example:

    class MimicObject {
      get [Symbol.toStringTag]() {
        return 'Object';
      }
    }
    

    The problem here is that when calling Object.prototype.toString on an instance of it, the false report [object Object] will be returned:

    let fakeObj = new MimicObject();
    Object.prototype.toString.call(fakeObj); // -> [object Object]
    

    But checking against the constructor gives a correct result:

    let fakeObj = new MimicObject();
    fakeObj.constructor === Object; // -> false
    
    0 讨论(0)
  • 2020-12-04 05:48

    The JavaScript specification gives exactly one proper way to determine the class of an object:

    Object.prototype.toString.call(t);
    

    http://bonsaiden.github.com/JavaScript-Garden/#types

    0 讨论(0)
  • 2020-12-04 05:49

    Accepted answer is correct, but I like to define this little utility in most projects I build.

    var types = {
       'get': function(prop) {
          return Object.prototype.toString.call(prop);
       },
       'null': '[object Null]',
       'object': '[object Object]',
       'array': '[object Array]',
       'string': '[object String]',
       'boolean': '[object Boolean]',
       'number': '[object Number]',
       'date': '[object Date]',
    }
    

    Used like this:

    if(types.get(prop) == types.number) {
    
    }
    

    If you're using angular you can even have it cleanly injected:

    angular.constant('types', types);
    
    0 讨论(0)
  • 2020-12-04 05:57
    var o = ...
    var proto =  Object.getPrototypeOf(o);
    proto === SomeThing;
    

    Keep a handle on the prototype you expect the object to have, then compare against it.

    for example

    var o = "someString";
    var proto =  Object.getPrototypeOf(o);
    proto === String.prototype; // true
    
    0 讨论(0)
  • 2020-12-04 05:58

    The best solution is toString (as stated above):

    function getRealObjectType(obj: {}): string {
        return Object.prototype.toString.call(obj).match(/\[\w+ (\w+)\]/)[1].toLowerCase();
    }
    

    FAIR WARNING: toString considers NaN a number so you must manually safeguard later with Number.isNaN(value).

    The other solution suggested, using Object.getPrototypeOf fails with null and undefined

    0 讨论(0)
提交回复
热议问题