Check if a value is an object in JavaScript

Asked 2023-09-20 20:55:12 View 406,392

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

  • A variable is a variable. It may refer to an object. Also, you may want to define "object" - as the answers and comments show, there are various conflicting definitions (e.g. whether null is an object). - anyone
  • OP, IMO you should accept @Daan's answer as it is the best solution and should be listed above other answers so it is seen first. (No offense to others who also have good answers.) - anyone
  • IMHO it really depends on what you (the one seeking for an answer to this question) consider an Object, and why you are checking it. This question gives different answers if you are trying to distinguish Arrays (that are Objects) from other Objects or if you are trying to separate scalar values from "vectors". And whether null (that is an Object, according to typeof) or Functions (that are Objects) should be excluded or not, it really depends on why you are checking it. That's why there are so many answers and most of them, in context, are correct. - anyone
  • It would be great if you could start by saying what exactly you mean by "is an Object". (Or, say explicitly that part of the answer you're seeking is to nail down various popular meanings of "is an object" and then differentiate between them.) Lacking that, everyone is talking past each other. - anyone
  • @tiffon How about a to the point answer at stackoverflow.com/a/52478680/1096194. I wrote this when I was overwhelmed by seeing the length of detail in many of the highest voted answers. I believe it deserves a lot more visibility. - anyone

Answers

If typeof yourVariable === 'object', it's an object or null.

If you want null, arrays or functions to be excluded, just make it:

if (
    typeof yourVariable === 'object' &&
    !Array.isArray(yourVariable) &&
    yourVariable !== null
) {
    executeSomeCode();
}

Answered   2023-09-20 20:55:12

  • Functions are also objects and should be included in your check. - anyone
  • In this case would yourVariable !== null be better practice? - anyone
  • @RightSaidFred Seems that typeof null == 'object' will not be fixed in ES6. They said: This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible. - anyone
  • @Tresdin The best way is to run Object.prototype.toString.call(yourVar), being yourVar what you need to inspect. In case of arrays, Object.prototype.toString.call([1,2]) returns [object Array] - anyone
  • Downvoted because an array is also considered an object, so you should also check Array.isArray(yourVariable). - anyone

UPDATE:

This answer is incomplete and gives misleading results. For example, null is also considered of type object in JavaScript, not to mention several other edge cases. Follow the recommendation below and move on to other "most upvoted (and correct!) answer":

typeof yourVariable === 'object' && yourVariable !== null

Original answer:

Try using typeof(var) and/or var instanceof something.

EDIT: This answer gives an idea of how to examine variable's properties, but it is not a bulletproof recipe (after all there's no recipe at all!) for checking whether it's an object, far from it. Since people tend to look for something to copy from here without doing any research, I'd highly recommend that they turn to the other, most upvoted (and correct!) answer.

Answered   2023-09-20 20:55:12

  • This answer is incorrect. typeof returns 'object' for null, which is not an object, and instanceof doesn't work for objects created using Object.create(null). - anyone
  • typeof null... object! - anyone
  • Arrays will also return as "objects" as in: someArray instanceof Object //true or typeof someArray === 'object' // true. What about: Object.prototype.toString.call(someObject) === "[object Object]", or "[object Array]" if you're trying to detect an array? - anyone
  • @Jonathan, there are better reasons for downvoting my answer, do you by chance have military background? :) - anyone
  • This should not be the accepted answer. Beyond the stylistic concerns raised by Jonathan, it is simply incorrect and does not bring up the very important subtleties in e.g. @matt-fenwick's answer. - anyone

Let's define "object" in Javascript. According to the MDN docs, every value is either an object or a primitive:

primitive, primitive value

A data that is not an object and does not have any methods. JavaScript has 7 primitive data types: string, number, bigint, boolean, undefined, symbol, and null.

What's a primitive?

  • 3
  • 'abc'
  • true
  • null
  • undefined

What's an object (i.e. not a primitive)?

  • Object.prototype
  • everything descended from Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} -- user-defined functions
    • C.prototype -- the prototype property of a user-defined function: this is not Cs prototype
      • new C() -- "new"-ing a user-defined function
    • Math
    • Array.prototype
      • arrays
    • {"a": 1, "b": 2} -- objects created using literal notation
    • new Number(3) -- wrappers around primitives
    • ... many other things ...
  • Object.create(null)
  • everything descended from an Object.create(null)

How to check whether a value is an object

instanceof by itself won't work, because it misses two cases:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}

typeof x === 'object' won't work, because of false positives (null) and false negatives (functions):

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}

Object.prototype.toString.call won't work, because of false positives for all of the primitives:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"

So I use:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}

@Daan's answer also seems to work:

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

because, according to the MDN docs:

The Object constructor creates an object wrapper for the given value. If the value is null or undefined, it will create and return an empty object, otherwise, it will return an object of a type that corresponds to the given value. If the value is an object already, it will return the value.


A third way that seems to work (not sure if it's 100%) is to use Object.getPrototypeOf which throws an exception if its argument isn't an object:

// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)

// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})

Answered   2023-09-20 20:55:12

  • obj === Object(obj) returns true for arrays. - anyone
  • var x = []; console.log(x === Object(x)); // return true - anyone
  • @Illuminator arrays are objects in Javascript, as I mentioned in my answer. - anyone
  • getPrototypeOf does not work e.g. with revoked proxies, which are objects but throw. - anyone
  • Why not ({}).toString.apply(obj) === '[object Object]' this distinguishes between arrays and objects that are not arrays - anyone

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;
};

Answered   2023-09-20 20:55:12

  • In javascript an array is also an object, so most of the time you want to exclude the array: return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]' - anyone
  • why would you exclude an array? They are full-fledged objects. - anyone
  • Because most of the time you want to distinguish an {} from a [] for example as input in a function - anyone
  • @Nickolai ..and for iterating through nested objects. - anyone
  • Great answer. Handles null, too. Should be the accepted answer. - anyone

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.

Answered   2023-09-20 20:55:12

  • I recently learned that typeof [] === 'object' --> true. That's what you need this method. - anyone
  • @Christophe Doesn't distinguish between primitives and objects. Object.prototype.toString.call(3) -> "[object Number]". Object.prototype.toString.call(new Number(3)) -> "[object Number]" - anyone
  • @MattFenwick I don't think this is the kind of "object" the OP is trying to identify - anyone
  • @Christophe why do you think that? IMHO, in the absence of any other definition given by the OP for "object", it seems most reasonable to me to go with the one that is used consistently throughout the ECS spec. - anyone
  • getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];}; - anyone

For simply checking against Object or Array without additional function call (speed). As also posted here.

isArray()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isLiteralObject() - Note: use for Object literals only, as it returns false for custom objects, like new Date or new YourCustomObject.

isLiteralObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isLiteralObject(        )); // false
console.log(isLiteralObject(    null)); // false
console.log(isLiteralObject(    true)); // false
console.log(isLiteralObject(       1)); // false
console.log(isLiteralObject(   'str')); // false
console.log(isLiteralObject(      [])); // false
console.log(isLiteralObject(new Date)); // false
console.log(isLiteralObject(      {})); // true

Answered   2023-09-20 20:55:12

  • @zupa: what !!a does? - anyone
  • @3000 well, if we leave out the (!!a) part it crashes, because null and undefined have no constructors. (!!a) filters them out. Does that answer your question? - anyone
  • @zupa @3000 Boolean(a) is longer, but far more intuitive. Just don't use new Boolean(a): (here's why)! - anyone
  • Surprised the best answer is so far down the page. This basically answers the question- would this be represented in JSON as something starting with a { character. For the array case, as long as you don't need to support IE < 9, you can use Array.isArray() to determine if something is an array. It passes all the test cases you provided. - anyone
  • @BradKent Without the double negative !!a isObject(null) would return null instead of false - anyone

I'm fond of simply:

function isObject (item) {
  return (typeof item === "object" && !Array.isArray(item) && item !== null);
}

If the item is a JS object, and it's not a JS array, and it's not null…if all three prove true, return true. If any of the three conditions fails, the && test will short-circuit and false will be returned. The null test can be omitted if desired (depending on how you use null).

DOCS:

http://devdocs.io/javascript/operators/typeof

http://devdocs.io/javascript/global_objects/object

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null

Answered   2023-09-20 20:55:12

  • What about console.log(isObject(new Date()))? Why should a date be an object but an array not? - anyone
  • @macher Because new Date() returns an object. An array is from a logical point of view not an object - although JavaScript handles and reports them as such. In practice however, it is not helpful to see them equal, because they are not. An object has no length attribute for example and it has no methods like push(). And sometimes you might want to give a function overloaded params, where you need to make a difference between an array or an object especially if other parameters depend on which one was given. - anyone
  • @StanE Arrays are definitely objects. Not sure why you think objects can't have a length property nor methods like push, Object.create(Array.prototype) is a trivial counterexample of a non-array object which has these. What makes arrays special is that they are exotic objects with a custom [[DefineOwnProperty]] essential internal method, but they are still objects. - anyone
  • @Oriol I neither wrote that arrays are not objects nor did I wrote that objects can't have a length property (I meant that object literals have no length attribute by default). I wrote that arrays are not objects from a logical point of view. I'm speaking about program logic. It is sometimes necessary to check if an array is a "real" array and definitely not an "real" object. That's what Array.isArray() is for. Imagine you have a function which accepts an object or an array of objects. Checking for a special attribute or method is a dirty solution. The native way is always better. - anyone
  • typeof null is "object", not "undefined". - anyone

With function Array.isArray:

function isObject(o) {
  return o !== null && typeof o === 'object' && Array.isArray(o) === false;
}

Without function Array.isArray:

Just surprised how many upvotes for wrong answers 😮
Only 1 answer passed my tests!!! Here I've created my simplified version:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

As for me, it's clear and simple, and just works! Here my tests:

console.log(isObject({}));             // Will return: true
console.log(isObject([]));             // Will return: false
console.log(isObject(null));           // Will return: false
console.log(isObject(/.*/));           // Will return: false
console.log(isObject(function () {})); // Will return: false

ONE MORE TIME: not all answers pass this tests !!! 🙈


In case you need to verify that object is instance of particular class you have to check constructor with your particular class, like:

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

simple test:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

As result, you will have strict and robust code!


In case you won't create functions like isDate, isError, isRegExp, etc you may consider option to use this generalized functions:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

it won't work correctly for all test cases mentioned earlier, but it's good enough for all objects (plain or constructed).


isObject won't work in case of Object.create(null) because of internal implementation of Object.create which is explained here but you can use isObject in more sophisticated implementation:

function isObject(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
};

There is already created package on npm v1 based on this implementation! And it works for all earlier described test cases! 🙂

Answered   2023-09-20 20:55:12

  • best answer! works for many of cases mentioned here - anyone
  • Because this returns false for isObject(myDateObject), this is not an answer to the question. It does not tell if a variable is an object, only if it is an object of a specific class. The question here is for a generic function that returns true for any object. - anyone
  • @Yetanotherjosh It is an answer indeed 🤓 you mentioned case which is described in answer, and the point - you have to use isDate for yourDateObject with purpose to write robust code otherwise you will have brittle isObject method. - anyone
  • @VladimirKovpak Using Date in my comment was ill-chosen because yes, the answer does discuss Date. But Date is just one of infinite possible classes and the point holds for any other class. Example: class Foo() { }; var x = new Foo(); isObject(x) returns false. I don't know exactly what the OP's use case is, but it's easy to conceive of scenarios in which having to know about all possible classes and checking specifically against every one of them is going to be infeasible. - anyone
  • @Yetanotherjosh I've updated my answer. And added 1 more case. - anyone

Oh My God! I think this could be more shorter than ever, let see this:

Short and Final code

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false

Explained

Return Types

typeof JavaScript objects (including null) returns "object"

console.log(typeof null, typeof [], typeof {})

Checking on Their constructors

Checking on their constructor property returns function with their names.

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property

Introducing Function.name

Function.name returns a readonly name of a function or "anonymous" for closures.

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property

Note: As of 2018, Function.name might not work in IE

Answered   2023-09-20 20:55:12

  • I really like this one, short and to the point. It only fails on 1 thing as far as I can see. if obj = Object.create(null) and quite why you would do that anyway...? - anyone
  • If you like, you can exclude that rare case: return obj != null && obj.constructor && obj.constructor.name === "Object" The condition 'obj.constructor' returns false because Object.create(null) creates an object with no properties, not even .__proto__ or .constructor. - anyone
  • Based on your answer, my final (ES11) helper in NodeJS is: const isObject = (obj) => (obj ?? false)?.constructor?.name === "Object"; Thank you! - anyone

Try this

if (objectName instanceof Object) {
  alert('An object');
} else {
  alert('Not an object');
}

Answered   2023-09-20 20:55:12

  • This misses two cases: Object.prototype instanceof Object -> false. Object.create(null) instanceof Object -> false. - anyone
  • what about dates? new Date() instanceof Object => true - anyone
  • this code is assuming array as object. - anyone
  • That's because both Dates and arrays are objects. - anyone

OK, let's give you this concept first before answering your question, in JavaScript Functions are Object, also null, Object, Arrays and even Date, so as you see there is not a simple way like typeof obj === 'object', so everything mentioned above will return true, but there are ways to check it with writing a function or using JavaScript frameworks, OK:

Now, imagine you have this object that's a real object (not null or function or array):

var obj = {obj1: 'obj1', obj2: 'obj2'};

Pure JavaScript:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

or

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}

or

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

or

function isObject(obj) {
    return obj instanceof Object;
}

You can simply use one of these functions as above in your code by calling them and it will return true if it's an object:

isObject(obj);

If you are using a JavaScript framework, they usually have prepared these kind of functions for you, these are few of them:

jQuery:

 //It returns 'object' if real Object;
 jQuery.type(obj);

Angular:

angular.isObject(obj);

Underscore and Lodash:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);

Answered   2023-09-20 20:55:12

  • You also want to check that it isn't an array. so function isObject(obj) { return obj !== null && typeof obj === 'object' && !Array.isArray(obj); } - anyone
  • I agree with you, but as you see in the comment, it's how it's done in angularJs and I mention it in the comment in front of the function, they count the Array as an Object ... look at here for more information: docs.angularjs.org/api/ng/function/angular.isObject - anyone

It depends on what you mean with "is an object". If you want everything that is not a primitive, i.e. things that you can set new properties on, this should do the trick:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

It excludes the primitives (plain numbers/NaN/Infinity, plain strings, symbols, true/false, undefined and null) but should return true for everything else (including Number, Boolean and String objects). Note that JS does not define what "host" objects, such as window or console, should return when used with typeof, so those are hard to cover with a check like this.

If you want to know whether something is a "plain" object, i.e. it was created as a literal {} or with Object.create(null), you might do this:

function isPlainObject(value) {
    if (Object.prototype.toString.call(value) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(value);
        return prototype === null || prototype === Object.prototype;
    }
}

Edit 2018: Because Symbol.toStringTag now allows customizing the output of Object.prototype.toString.call(...), the isPlainObject function above might return false in some cases even when the object started its life as a literal. Arguably, by convention an object with a custom string tag isn't exactly a plain object any more, but this has further muddied the definition of what a plain object even is in Javascript.

Answered   2023-09-20 20:55:12

  • Why is typeof === 'function' considered to be an object? A function is not an object, isn't it? "new myFunc()" will become an object, yes, but a plain function? - anyone
  • No, every function is an object in Javascript, regardless of how it was created. You can set properties on them (unless they are frozen), they are instanceof Object, two identical function literals are not strictly equal, they are passed by reference, etc. - anyone

My God, too much confusion in other answers.

Short Answer

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

To test this simply run the following statements in chrome console.

Case 1.

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

Case 2.

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

Case 3.

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

Explanation

Okay.Let's break it down

typeof anyVar == 'object' is returned true from three candidates - [], {} and null,

anyVar instanceof Object narrows down these candidates to two - [], {}

!(anyVar instanceof Array) narrows to only one - {}

Drum rolls please!

By this you may have already learnt how to check for Array in Javascript.

Answered   2023-09-20 20:55:12

  • Of note, this also returns false (as desired) when anyVar is a function. - anyone
  • Nice answer @HalfWebDev, but to cater for functions as commented by Jamie Birch, we can do this typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) && typeof anyVar !== 'function' - anyone
  • new Date() will return true here. Can fix with !(anyVar instanceof Date) - anyone

Here's an answer with optional chaining, and perhaps the smallest isObj function for this question.

const isObj = o => o?.constructor === Object;

// True for this
console.log(isObj({}));        // object!

// False for these
console.log(isObj(0));         // number
console.log(isObj([]));        // array
console.log(isObj('lol'));     // string
console.log(isObj(null));      // null
console.log(isObj(undefined)); // undefined
console.log(isObj(() => {}));  // function
console.log(isObj(Object));    // class

Answered   2023-09-20 20:55:12

  • new Error() would be false in your function. - anyone
  • @TinyRoy isn't that how it's supposed to be? An error instance is not an object. Let me know if I got something wrong. :) - anyone
  • If your intension is to exclude instances that inherit from Object, then you are right but I see them as objects. They have all the properties of an object. - anyone
  • I believe that is what the question asked. Otherwise basically everything inherits from Object. - anyone
  • what does the '?" sign means? - anyone

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.

Answered   2023-09-20 20:55:12

  • "Only my answer and Daan's are entirely correct." is a bit presumptuous given that I entirely disagree with your first two sentences. - anyone
  • @zzzzBov Well, I looked at all answers and they do not ensure to always return the proper answer, except mine and Daan's. I can give reproducible counterexamples to most of them. The others recommend checking if typeof returns "function" or "object", but as I explained, the spec allows other results for some objects. Matt Fenwick's answer contains the same correct answer as Daan's, but also contains incorrect ones. - anyone
  • I disagreed with the premise that your answer is "entirely correct", arguing that others "do not ensure to always return the proper answer" does not refute my position in any way. Additionally, the question does not make any claims regarding what input should produce what output. - anyone
  • @zzzzBov The question asks how to check if something is an object. ECMAScript defines what an object is, so I use that definition. I can't see any other reasonable interpretation. Answers that do other things (like excluding arrays) can be useful in some circumstances, but they don't check if something is an object. - anyone
  • @Oriol Perhaps you could provide an Answer to this Question Why is there not a built-in method in JavaScript to check if an object is a plain object? ? - anyone

Ready to use functions for checking

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// Loose equality operator (==) is intentionally used to check
// for undefined too

// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null

Explanation

  • In Javascript, null, Object, Array, Date and functions are all objects. Although, null is bit contrived. So, it's better to check for the null first, to detect it's not null.

  • Checking for typeof o === 'object' guarantees that o is an object. Without this check, Object.prototype.toString would be meaningless, since it would return object for everthing, even for undefined and null! For example: toString(undefined) returns [object Undefined]!

    After typeof o === 'object' check, toString.call(o) is a great method to check whether o is an object, a derived object like Array, Date or a function.

  • In isDerivedObject function, it checks for the o is a function. Because, function also an object, that's why it's there. If it didn't do that, function will return as false. Example: isDerivedObject(function() {}) would return false, however now it returns true.

  • One can always change the definition of what is an object. So, one can change these functions accordingly.


Tests

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);

Answered   2023-09-20 20:55:12

  • Hi ! Great post but has a minor typo even if it yields correct result: console.log( 'is (new (function (){})) a derived object?', isObject((new (function (){}))) ); - anyone

Little late... for "plain objects" (i mean, like {'x': 5, 'y': 7}) i have this little snippet:

function isPlainObject(o) {
   return (o === null || Array.isArray(o) || typeof o == 'function' || o.constructor === Date ) ?
           false
          :(typeof o == 'object');
}

It generates the next output:

console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false

It always works for me. If will return "true" only if the type of "o" is "object", but no null, or array, or function. :)

Answered   2023-09-20 20:55:12

  • As mentioned in the previous answers your approach will fail in case of the Date object. - anyone

If you would like to check if the prototype for an object solely comes from Object. Filters out String, Number, Array, Arguments, etc.

function isObject (n) {
  return Object.prototype.toString.call(n) === '[object Object]';
}

Or as a single-expression arrow function (ES6+)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

Answered   2023-09-20 20:55:12

  • this is the best way but I would make it even easier by on the 2nd line: return Object.prototype.toString.call(n) === '[object Object]' - anyone
  • You can also remove the null check, because Object.prototype.toString.call(null) === '[object Null]' - anyone
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

var b ={a: 1}
b instanceof Object //true
b instanceof Array //false

var c = null
c instanceof Object //false
c instanceof Array //false

I was asked to provide more details. Most clean and understandable way of checking if our variable is an object is typeof myVar. It returns a string with a type (e.g. "object", "undefined").

Unfortunately either Array and null also have a type object. To take only real objects there is a need to check inheritance chain using instanceof operator. It will eliminate null, but Array has Object in inheritance chain.

So the solution is:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

Answered   2023-09-20 20:55:12

  • /./ instanceof Object //true - anyone
  • if use final soution, function will be regarded as a object - anyone

lodash has isPlainObject, which might be what many who come to this page are looking for. It returns false when give a function or array.

Answered   2023-09-20 20:55:12

  • Perfect! I knew about _.isObject which matches what JS considers an object. But what I usually need is to differentiate between e.g. an object literal and an array, which is exactly what _.isPlainObject lets me do. - anyone

The Ramda functional library has a wonderful function for detecting JavaScript types.

Paraphrasing the full function:

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}

I had to laugh when I realized how simple and beautiful the solution was.

Example usage from Ramda documentation:

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"

Answered   2023-09-20 20:55:12

Performance

Today 2020.09.26 I perform tests on MacOs HighSierra 10.13.6 on Chrome v85, Safari v13.1.2 and Firefox v80 for chosen solutions.

Results

  • solutions C and H are fast/fastest on all browsers for all cases
  • solutions D and G are slow/slowest on all browsers for all cases

enter image description here

Details

I perform 3 tests cases for solutions A B C D E F G H I J K L M N O P Q R S T U V

  • for small object - you can run it HERE
  • for big object - you can run it HERE
  • for no object - you can run it HERE

Below snippet presents differences between solutions. Solutions A-G give proper answers for chosen cases described by Matt Fenwick

// https://stackoverflow.com/a/14706877/860099
function A(x) {
  return x === Object(x);
};

// https://stackoverflow.com/a/42250981/860099
function B(x) {
    return _.isObject(x);
}

// https://stackoverflow.com/a/34864175/860099
function C(x) {
    return x != null && (typeof x === 'object' || typeof x === 'function');
}

// https://stackoverflow.com/a/39187058/860099
function D(x) { 
  return new function() { return x; }() === x;
}

// https://stackoverflow.com/a/39187058/860099
function E(x) { 
  return function() { return this === x; }.call(x);
}

// https://stackoverflow.com/a/39187058/860099
function F(x) { /* Requires ECMAScript 5 or later */
  try {
    Object.create(x);
    return x !== null;
  } catch(err) {
    return false;
  }
}

// https://stackoverflow.com/a/39187058/860099
function G(x) { /* Requires ECMAScript 5 or later */
  function Constructor() {}
  Constructor.prototype = x;
  return Object.getPrototypeOf(new Constructor()) === x;
}

// https://stackoverflow.com/a/8511332/860099
function H(x) {
  return typeof x === 'object' && x !== null
}

// https://stackoverflow.com/a/25715455/860099
function I(x) {
  return (typeof x === "object" && !Array.isArray(x) && x !== null);
};

// https://stackoverflow.com/a/22482737/860099
function J(x) {
  return x instanceof Object; 
}

// https://stackoverflow.com/a/50712057/860099
function K(x)
{
    let t= JSON.stringify(x);
    return t ? t[0] === '{' : false;
}

// https://stackoverflow.com/a/13356338/860099
function L(x) {
  return Object.prototype.toString.call(x) === "[object Object]";
};



// https://stackoverflow.com/a/46663081/860099
function M(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
}

// https://stackoverflow.com/a/42250981/860099
function N(x) {
    return $.type(x) === 'object';
}

// https://stackoverflow.com/a/34864175/860099
function O(x) {
    if (Object.prototype.toString.call(x) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(x);
        return prototype === null || prototype === Object.prototype;
    }
}

// https://stackoverflow.com/a/57863169/860099
function P(x) {
  while (     Object.prototype.toString.call(x) === '[object Object]')
  if    ((x = Object.getPrototypeOf(x))         === null)
  return true
  return false
}

// https://stackoverflow.com/a/43289971/860099
function Q(x){
  try{
    switch(x.constructor){
      case Number:
      case Function:
      case Boolean:
      case Symbol:
      case Date:
      case String:
      case RegExp:
        return x.constructor === Object;
      case Error:
      case EvalError:
      case RangeError:
      case ReferenceError:
      case SyntaxError:
      case TypeError:
      case URIError:
        return (Object === Error ? Error : x.constructor) === Object;
      case Array:
      case Int8Array:
      case Uint8Array:
      case Uint8ClampedArray:
      case Int16Array:
      case Uint16Array:
      case Int32Array:
      case Uint32Array:
      case Float32Array:
      case Float64Array:
        return (Object === Array ? Array : x.constructor) === Object;
      case Object:
      default:
        return (Object === Object ? Object : x.constructor) === Object;
    }
  } catch(ex){
    return x == Object;   
  }
}

// https://stackoverflow.com/a/52478680/860099
function R(x) {
    return typeof x == 'object' && x instanceof Object && !(x instanceof Array);
}

// https://stackoverflow.com/a/51458052/860099
function S(x)
{
    return x != null && x.constructor?.name === "Object"
}

// https://stackoverflow.com/a/42250981/860099
function T(x) {
    return x?.constructor?.toString().indexOf("Object") > -1;
}

// https://stackoverflow.com/a/43223661/860099
function U(x)
{
    return x?.constructor === Object;
}

// https://stackoverflow.com/a/46663081/860099
function V(x) {
  return x instanceof Object && x.constructor === Object;
}




// -------------
// TEST
// -------------

console.log('column: 1 2 3 4 5 6 - 7 8 9 10 11');

[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V]
.map(f=> console.log(`${f.name}:      ${1*f(new Date())} ${1*f(/./)} ${1*f({})} ${1*f(Object.prototype)} ${1*f(Object.create(null))} ${1*f(()=>{})} - ${1*f("abc")} ${1*f(3)} ${1*f(true)}  ${1*f(null)}  ${1*f(undefined)}`))

console.log(`
Columns legend (test cases):
 1: new Date()
 2: /./ (RegExp)
 3: {}
 4: Object.prototype
 5: Object.create(null)
 6: ()=>{} (function)
 7: "abc" (string)
 8: 3 (number)
 9: true (boolean)
10: null
11: undefined

Rows:
1 = is object
0 = is NOT object

Theoretically columns 1-6 should have have 1, columns 7-11 shoud have 0
`);
<script
  src="https://code.jquery.com/jquery-3.5.1.min.js"
  integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
  crossorigin="anonymous"></script>
  
<script 
  src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" 
  integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" 
  crossorigin="anonymous"></script>
  
This shippet only presents functions used in performance tests - it not perform tests itself!

And here are example results for chrome

enter image description here

Answered   2023-09-20 20:55:12

Since there seems a lot of confusion about how to handle this problem correctly, I'll leave my 2 cents (this answer is spec compliant and produces correct results under all circumstances):

Testing for primitives: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}

An object is not a primitive:

function isObject(o){return !isPrimitive(o)}

Or alternatively:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}

Testing for any Array:

const isArray=(function(){
    const arrayTypes=Object.create(null);
    arrayTypes['Array']=true;
    arrayTypes['Int8Array']=true;
    arrayTypes['Uint8Array']=true;
    arrayTypes['Uint8ClampedArray']=true;
    arrayTypes['Int16Array']=true;
    arrayTypes['Uint16Array']=true;
    arrayTypes['Int32Array']=true;
    arrayTypes['Uint32Array']=true;
    arrayTypes['BigInt64Array']=true;
    arrayTypes['BigUint64Array']=true;
    arrayTypes['Float32Array']=true;
    arrayTypes['Float64Array']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
    }
}());

Testing for object excluding: Date RegExp Boolean Number String Function any Array

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());

Answered   2023-09-20 20:55:12

After reading and trying out a lot of implementations, I've noticed that very few people try to check for values like JSON, Math, document or objects with prototype chains longer than 1 step.

Instead of checking the typeof of our variable and then hacking away edge-cases, I thought it'd be better if the check is kept as simple as possible to avoid having to refactor when there's new primitives or native objects added that register as typeof of 'object'.

After all, the typeof operator will tell you if something is an object to JavaScript, but JavaScript's definition of an object is too broad for most real-world scenarios (e.g. typeof null === 'object'). Below is a function that determines whether variable v is an object by essentially repeating two checks:

  1. A loop is started that continues as long as the stringified version of v is '[object Object]'.
    I wanted the result of the function to be exactly like the logs below, so this is the only "objectness"-criteria I ended up with. If it fails, the function returns false right away.
  2. v is replaced with the next prototype in the chain with v = Object.getPrototypeOf(v), but also directly evaluated after. When the new value of v is null, it means that every prototype including the root prototype (which could very well have been the only prototype inside the chain) have passed the check in the while loop and we can return true. Otherwise, a new iteration starts.

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype     -> ', isObj(Object.prototype))
console.log('Object.create(null)  -> ', isObj(Object.create(null)))
console.log('Object.create({})    -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))

Answered   2023-09-20 20:55:12

When everything else fails, I use this:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

Answered   2023-09-20 20:55:12

  • Why the string comparison, why not simply item.constructor === Object? - anyone
  • null throws an exception Uncaught TypeError: Cannot read property 'constructor' of null(…) - anyone
  • @rounce I am aiming to support older IE versions, why does it not work in IE? Because of the indexOf or because of constructor.name? - anyone
  • This will fail with undefined too. - anyone
  • if your variable can't have falsy value varName && varName.constructor.name === "Object" if your variable may have falsy value varName != null && varName != undefined && varName.constructor.name === "Object" - anyone

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

Answered   2023-09-20 20:55:12

  • @SeregPie In future you should refrain from editing code in answers. As this answer stands, when testing I did obtain null as the result for the final test rather than false. See When should I make edits to code? - anyone

For the purpose of my code I found out this decision which corresponds with some of the answers above:

ES6 variant:

const checkType = o => Object.prototype
                    .toString
                    .call(o)
                    .replace(/\[|object\s|\]/g, '')
                    .toLowerCase();

ES5 variant:

function checkType(o){
   return Object.prototype
                    .toString
                    .call(o)
                    .replace(/\[|object\s|\]/g, '')
                    .toLowerCase();
}

You can use it very simply:

checkType([]) === 'array'; // true
checkType({}) === 'object'; // true
checkType(1) === 'number'; // true
checkType('') === 'string'; // true
checkType({}.p) === 'undefined'; // true
checkType(null) === 'null'; // true

and so on..

Answered   2023-09-20 20:55:12

  • alternatively slice(8, -1) could be used instead of replace(/\[|object\s|\]/g, ''). It runs horribly faster. - anyone
  • Yes, thanks! :) - anyone
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}

Answered   2023-09-20 20:55:12

  • And of course it will be false for the object Object.assign({}, {constructor: null}). - anyone
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!obj is shorthand for checking if obj is truthy (to filter out null)

Answered   2023-09-20 20:55:12

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

Answered   2023-09-20 20:55:12

  • pops true for new Date() - anyone
  • @toddmo thanks for pointing that out. Now the example code returns false for new Date() - anyone