Check if a value is an object in JavaScript

后端 未结 30 3394
臣服心动
臣服心动 2020-11-22 05:06

How do you check if a value is an object in JavaScript?

相关标签:
30条回答
  • 2020-11-22 05:45

    underscore.js provides the following method to find out if something is really an object:

    _.isObject = function(obj) {
      return obj === Object(obj);
    };
    

    UPDATE

    Because of a previous bug in V8 and minor micro speed optimization, the method looks as follows since underscore.js 1.7.0 (August 2014):

    _.isObject = function(obj) {
      var type = typeof obj;
      return type === 'function' || type === 'object' && !!obj;
    };
    
    0 讨论(0)
  • 2020-11-22 05:45

    It is an old question but thought to leave this here. Most people are checking if the variable is {} meaning a key-value paired and not what is the underline construct that JavaScript is using for a given thing, cuz to be honest mostly everything in JavaScript is an object. So taking that out of the way. If you do...

    let x = function() {}
    typeof x === 'function' //true
    x === Object(x) // true
    x = []
    x === Object(x) // true
    
    // also
    x = null
    typeof null // 'object'
    

    Most of the time what we want is to know if we have a resource object from an API or our database call returned from the ORM. We can then test if is not an Array, is not null, is not typeof 'function', and is an Object

    // To account also for new Date() as @toddmo pointed out
    
    x instanceof Object && x.constructor === Object
    
    x = 'test' // false
    x = 3 // false
    x = 45.6 // false
    x = undefiend // false
    x = 'undefiend' // false
    x = null // false
    x = function(){} // false
    x = [1, 2] // false
    x = new Date() // false
    x = {} // true
    
    0 讨论(0)
  • 2020-11-22 05:46

    The most reasonable way to check the type of a value seems the typeof operator. The only problem is that it's horribly broken:

    • It returns "object" for null, which belongs to Null type.
    • It returns "function" for callable objects, which belong to Object type.
    • It can return (almost) anything it wants for non-standard non-callable objects. For example, IE seemed to like "unknown". The only forbidden results are "function" and primitive types.

    typeof is only reliable for non-null primitives. So a way to check if a value is an object would be ensuring that the string returned by typeof does not correspond to a primitive, and that the object is not null. However, the problem is that a future standard could introduce a new primitive type, and our code would consider it to be an object. New types don't appear frequently, but for example ECMAScript 6 introduced the Symbol type.

    Therefore, instead of typeof, I only recommend approaches whose result varies depending on if the value is an object or not. The following intends to be a

    Comprehensive but not exhaustive list of proper ways to test if a value belongs to the Object type.

    • Object constructor

      The Object constructor coerces the passed argument to an object. If it's already an object, the same object is returned.

      Therefore, you can use it to coerce the value to an object, and strictly compare that object with the original value.

      The following function requires ECMAScript 3, which introduced ===:

      function isObject(value) { /* Requires ECMAScript 3 or later */
        return Object(value) === value;
      }
      

      I like this approach because it's simple and self-descriptive, and an analogous check will also work for booleans, numbers and strings. However, be aware it relies on the global Object not being shadowed nor altered.

    • Constructors

      When you instantiate a constructor, it can return a value different than the just-created instance. But that value will be ignored unless it's an object.

      The following function requires ECMAScript 3, which allowed constructors to return non-objects. Before ECMAScript 3 that threw an error, but try statements didn't exist back then.

      function isObject(value) { /* Requires ECMAScript 3 or later */
        return new function() { return value; }() === value;
      }
      

      While a bit less simple than the previous example, this one does not rely on any global property, and thus might be the safest.

    • this value

      Old ECMAScript specifications required the this value to be an object. ECMAScript 3 introduced Function.prototype.call, which allowed to call a function with an arbitrary this value, but coerced to an object.

      ECMAScript 5 introduced a strict mode which removed this behavior, but in sloppy mode we still can (but arguably shouldn't) rely on it.

      function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
        return function() { return this === value; }.call(value);
      }
      
    • [[Prototype]]

      All ordinary objects have an internal slot called [[Prototype]], whose value determines from which other object it inherits from. The value can only be an object or null. Therefore, you can attempt to create an object which inherits from the desired value, and check if it worked.

      Both Object.create and Object.getPrototypeOf require ECMAScript 5.

      function isObject(value) { /* Requires ECMAScript 5 or later */
        try {
          Object.create(value);
          return value !== null;
        } catch(err) {
          return false;
        }
      }
      
      function isObject(value) { /* Requires ECMAScript 5 or later */
        function Constructor() {}
        Constructor.prototype = value;
        return Object.getPrototypeOf(new Constructor()) === value;
      }
      
    • Some new ECMAScript 6 ways

      ECMAScript 6 introduces some new indirect ways to check is a value is an object. They use the previously seen approach to pass the value to some code which requires an object, wrapped inside a try statement to catch errors. Some hidden examples, not worth commenting

      function isObject(value) { /* Requires ECMAScript 6 or later */
        try {
          Object.setPrototypeOf({}, value);
          return value !== null;
        } catch(err) {
          return false;
        }
      }

      function isObject(value) { /* Requires ECMAScript 6 or later */
        try {
          new WeakSet([value]);
          return true;
        } catch(err) {
          return false;
        }
      }


    Note: I intentionally skipped some approaches like Object.getPrototypeOf(value) (ES5) and Reflect methods (ES6) because they call essential internal methods which might do nasty things, e.g. if value is a proxy. For safety reasons my examples only reference value without accessing it directly.

    0 讨论(0)
  • 2020-11-22 05:47

    This will work. It is a function that returns true, false, or possibly null.

    const isObject = obj => obj && obj.constructor && obj.constructor === Object;
    
    console.log(isObject({})); // true
    console.log(isObject([])); // false
    console.log(isObject(new Function)); // false
    console.log(isObject(new Number(123))); // false
    console.log(isObject(null)); // null

    0 讨论(0)
  • 2020-11-22 05:47

    If explicitly want to check if the given value is {}.

    function isObject (value) {
     return value && typeof value === 'object' && value.constructor === Object;
    }
    
    0 讨论(0)
  • 2020-11-22 05:50

    Object.prototype.toString.call(myVar) will return:

    • "[object Object]" if myVar is an object
    • "[object Array]" if myVar is an array
    • etc.

    For more information on this and why it is a good alternative to typeof, check out this article.

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