3

Given the developments of JavaScript since the languages' inception, why is there not a built in method that checks if an object is a plain object?

Or does the method in fact exist?

26
  • If I understood correctly I think instance of is one way.
    – Mritunjay
    Commented Nov 7, 2016 at 1:21
  • 4
    What exactly are you asking? What does an object is "[object Object]" mean in practical terms?
    – Pointy
    Commented Nov 7, 2016 at 1:23
  • "[object Object]" is just the output of Object.prototype.toString with any object as an argument. Commented Nov 7, 2016 at 1:24
  • 3
    Questions of the form "why does language X have/lack feature Y" are best directed at language implementors. JavaScript doesn't have lots of things.
    – Pointy
    Commented Nov 7, 2016 at 1:33
  • 1
    The question isn't relevant to the previous question. [] instanceof Object matches arrays because they are objects and prototypically inherit from Object. If you're relatively new to JS, this may take some time to get accustomed to the idea of prototypical inheritance. Then o instanceof Object && Array.isArray(o) should make perfect sense (btw, it doesn't cover Object.create(null)). Commented Nov 7, 2016 at 1:34

5 Answers 5

4

There doesn't exist any explicit direct way to check if a value is an object, i.e. belongs to Object type, but there are some foolproof ways to do it. I wrote a list in another answer, the most succinct seems

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

A feature like this has been requested multiple times on esdiscuss. For example,

In fact, Object.isObject was proposed as strawman, and it appeared in an ES6 early draft.

Object.isObject strawman was eventually rejected and removed from ES6 draft.

More recently,

Now there is the is{Type} Methods stage 0 proposal which includes Object.isObject among lots of various other checks.

So there is still hope and eventually we may have something like this.


The above is for testing objects in general. If you don't want that you should define what "plain object" means for you.

For example, you can test the constructor property. But any object can customize it.

You can use Object.prototype.toString to get the legacy ES5 [[Class]]. But any object can customize that via Symbol.toStringTag.

You can check the value returned by [[GetPrototypeOf]]. But even exotic objects might allow their prototype to be changed to whatever arbitrary object or null. And Proxy objects even have full control over that internal method.

So most probably you won't be able to rely on these tests. And adding something to the standard may be hard because different people may want different things.

What I would like is some way to check if an object is an ordinary one. That is, it has the default behaviour for the essential internal methods that must be supported by all objects.

Once you know that an object is ordinary, you can rely on things like [[GetPrototypeOf]] to customize the test to your tastes.

8
  • 3
    Note, Object can be assigned as an identifier. Object = 1; Object(1) === 1; Uncaught TypeError: Object is not a function, Object === 1 // true Commented Nov 15, 2016 at 0:58
  • 1
    @guest271314 In my list of ways to check if a value is an object there is an approach which does not require a sane environment: new function() { return value; }() === value
    – Oriol
    Commented Nov 15, 2016 at 2:48
  • Not certain how the pattern is used? Have been attempting to determing if a particular pattern is possible. Check if element is plain object is part of process. Other part is pattern itself. stackoverflow.com/questions/36232576/… , stackoverflow.com/questions/40541169/… Commented Nov 15, 2016 at 2:53
  • 1
    Trying to pass a function reference as a callback function which calls its own bound function with the value passed as parameter to original function call, then calls parameter function with same value before returning result. E.g., arr.filter(Object.is.bind(null, Object.prototype, Object.getProtototypeOf /* pass current element of arr` to Object.getProtototypeOf then call */)), or similar pattern, without explicitly using function(element, index, thisArg){}`; using only bound function references which are passed the current value. Or, determine if the pattern cannot be achieved. Commented Nov 15, 2016 at 3:33
  • 1
    This doesn't work for arrays as it returns true even though an array is not a plain javascript object. Commented Dec 3, 2021 at 17:16
4

You can check the type and the instance of an object this way:

var a = new Date();
console.log(typeof a);
console.log(a instanceof Date);

var b = "Hello";
console.log(typeof b);
console.log(b instanceof Date);

Updated according to the comments from the OP:

let arr = [1, 2, true, 4, {
    "abc": 123
  },
  6, 7, {
    "def": 456
  },
  9, [10], {}, "[object Object]"
];
arr.forEach(function(v) {
  if (typeof v == "object" && !(v instanceof Array) && v != null)
    console.log("Object Found");
  else
    ; // console.log("Na");
});

The above code snippets outputs thrice Object Found.

17
  • 1
    I guess this would answer the question accurately. Commented Nov 7, 2016 at 1:28
  • 1
    instanceof matches arrays as well, not only {} "[object Object]" Commented Nov 7, 2016 at 1:29
  • 1
    @PraveenKumar Yes. Your Answer returns expected result. Why is there not a built in JavaScript method to check if an object is "[object Object]"? Commented Nov 7, 2016 at 1:48
  • 1
    @guest271314 Er... :) I didn't develop JavaScript. Ha ha... Actually, this could be posed to the JavaScript Working Group. Good idea mate. If not you, I am gonna post it soon. Commented Nov 7, 2016 at 1:50
  • 1
    @guest271314 I am not sure. Will have a look for you... :) Commented Nov 7, 2016 at 1:55
3

Relying on [object Object] string representation is inaccurate. This behaviour may be changed for any objects with:

let o = { toString: () => '...' };
('' + o) !== '[object Object]'

var a = [];
a.toString = () => '[object Object]';
('' + a) === '[object Object]';

The most solid way to check if a value is a plain object is

let o = {}
Object.getPrototypeOf(o) === Object.prototype

And considering that constructor property wasn't tampered, the most straightforward way to check if a value is a plain object is

let o = {}
o.constructor === Object

This covers all POJOs constructed from Object and doesn't cover Object.create(null, { ... }) or any child classes (including built-ins like RegExp or Array):

Object.create(null).constructor !== Object
[].constructor !== Object
(new class {}).constructor !== Object

One of the possible reasons why there is no dedicated method to check for object plainness is because a restriction to use only {} objects is not practical. This makes very little sense in the context of JS. This prevents the use of any class instances or relatively 'plain' objects (Object.create({}, ...)).

This would require the hack in order for desired non-plain objects to pass the check:

Object.assign({}, (new class {})).constructor === Object

In most cases of object checking 'everything which is not forbidden is allowed' principle pays off (with extra caution regarding infamous null inconsistency).

Applying the above to this case, a safe and concise condition to filter non-array objects is

o && typeof o === 'object' && !Array.isArray(o)

And a condition to filter objects that are not built-ins (functions, Array, RegExp, etc) is

o && (o.constructor === Object || !/\[native code\]/.test(o.constructor))
19
  • What does "POJOs" mean? "and doesn't cover" Can you provide examples of what is not covered by the approach at Answer? That is Question. Why is there not a method that specifically checks for "[object Object]", that is, a plain object? Can you also elaborate on why checking for "[object Object]" is not reliable? Not sure gather first example entirely, here. Commented Nov 7, 2016 at 1:54
  • 1
    Plain Old JavaScript Object (adopted from Java). An informal term for {} objects (may or may not cover non-Object Object.create(null, { ... }) objects, depending on the context. Commented Nov 7, 2016 at 1:58
  • 1
    I've updated the question to cover the previous question. The reason is that such method is just generally not needed. The restriction to use a plain object can hardly be justified, and 'everything which is not forbidden is allowed' principle pays off. If a dev ever needs something specific condition to match, he/she has usually got a fair amount of fingers to write some helper function or use an existing one (or two). Commented Nov 7, 2016 at 3:37
  • 1
    There's no way for now. And it is unlikely that this will be changed in future because direct parentage checking is very low profile and it causes more problems than it solves - this is just against JS nature. And fortunately, it is something that can be done with a single line of code. There's nothing special about Object.create it self. The special cases are Object.create(null) (object prototype is undefined), Object.create({})` (object prototype is another object)... actually, anything but Object.create(Object.prototype). Commented Nov 7, 2016 at 23:42
  • 1
    __proto__ is is unstandardized. === does the job, Object.is is excessive here (it is === with benefits). Commented Nov 8, 2016 at 1:59
-1

Just for the sake of further documenting different ways:

One way I can think of:

JSON.stringify(testValue)[0] === '{';

Keep in mind that objects with circular references cannot be stringified. However, if you are certain that all testValues cannot have circular references, you have yourself a way to check against Null, Arrays, and any primitive value to ensure that you have an Object.

I suggest that if you plan on using this throughout your code though, that you define a helper function that actually implements it, in case you find that this does not work as you expect and end up having to change the way you check it.

-3

Every thing JavaScript is an Object , so there is no need to have an isObject api

5
  • That is not true: 2, true, "hello", undefined, null, NaN are all examples of values that are not objects (even though typeof null reports it is one). They are primitive values.
    – trincot
    Commented Nov 7, 2016 at 18:54
  • @trincot Technically, primitives are objects, i.e. instances of respective constructors (except undefined and null). But they are certainly not Object objects. Commented Nov 7, 2016 at 20:46
  • @estus, do you have a reference for "primitives are objects"? Quoted from MDN: "A primitive (primitive value, primitive data type) is data that is not an object". Maybe you were thinking of primitive wrapper objects?
    – trincot
    Commented Nov 7, 2016 at 20:56
  • @trincot It is less confusing to not think of them as of objects, but in fact, they are the ones, even though special ones. A statement from MDN is incorrect, A primitive (primitive value, primitive data type) is data that is not an object and has no methods. Primitives cannot have own methods but get the methods of their prototypes (and can gain new methods by prototype extension). ''.__proto__ === String.prototype && ''.constructor === String. Commented Nov 7, 2016 at 21:06
  • 1
    What you show at the end is an example of coercion: '' is not an object, but JavaScript will turn it into one when you reference a property like that. Although this seems to prove the string literal is an object, this is not the case. Indeed, ''.__proto__ really gets parsed as String('').__proto__. May I invite you to read The Secret Life of JavaScript Primitives which explains this quite well.
    – trincot
    Commented Nov 7, 2016 at 21:15

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.