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?
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?
Share Improve this question edited Nov 7, 2016 at 2:14 guest271314 asked Nov 7, 2016 at 1:18 guest271314guest271314 102k15 gold badges117 silver badges187 bronze badges 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. – Tibrogargan 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. Theno instanceof Object && Array.isArray(o)
should make perfect sense (btw, it doesn't coverObject.create(null)
). – Estus Flask Commented Nov 7, 2016 at 1:34
5 Answers
Reset to default 4There 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,
What is an Object Type(O)?
Juriy Zaytsev "kangax" wonders about a proper way to check if a value is an object.
typeof null
- Brendan Eich: "I think we should consider Object.isObject"
- Jorge: "Why not .isPrimitive()?"
ES6 doesn't need opt-in
- Brendan Eich: "We want sane isObject and isNull predicates"
- Axel Rauschmayer: "predicates such as isObject() and isPrimitive()"
In fact, Object.isObject
was proposed as strawman, and it appeared in an ES6 early draft.
TC39 bashing: Discussion about
Object.isObject
in the ES6 draft.How primitive are Symbols? Bignums? etc: discusses
x === Object(x)
Object.isObject
strawman was eventually rejected and removed from ES6 draft.
More recently,
- ES8 Proposal: Optional Static Typing (Brandon Andrews): Includes
Object.isObject
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.
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 ments 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
.
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))
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.
Every thing JavaScript is an Object , so there is no need to have an isObject api