typeof object but not array
If you want to check if an object is a "plain" object, i.e. inherits directly from Object.prototype, then you should check for that.
E.g. the following first tests if value has Object anywhere on it's prototype chain (and hence will not throw an error for getPrototypeOf), then checks if its immediate [[prototype]]
is Object.prototype:
function isPlainObject(value) {
return value instanceof Object &&
Object.getPrototypeOf(value) == Object.prototype;
}
// Some tests
[[1,2], // Array
{}, // Plain object
null, // null
document.createElement('div'), // host object
function(){}, // function object
console // host objet
].forEach(function(value) {
console.log(value + ': ' + isPlainObject(value));
});
Edit
If you want to test that the input is some extended object but not a Function, etc. that is much less efficient, e.g. test against some list of objects that you want to avoid:
function isJustObj(obj) {
var notThese = [Function, Array, Date];
if (obj instanceof Object) {
return !notThese.some(function(o) {
return obj instanceof o;
});
}
return false;
}
function Foo(){}
var tests = {'Array: ':[],
'Object: ' : {},
'Foo instance:' : new Foo(),
'Function: ' : function(){},
'Date: ' : new Date(),
'Host obj: ' : document.createElement('div')
};
Object.keys(tests).forEach(function(test) {
console.log(test + isJustObj(tests[test]));
})
Note that this strategy sees if the value is some kind of Object, then tests whether it's an instance of a particular set of constructors. This list of things to exclude can become very large since it's not possible in any reasonable way to rule out host objects which, by their very nature, can be indistinguishable from built-in objects based on some general test (see Is there an environment-agnostic way to detect Javascript Host Objects?).
E.g.
console.log instanceof Function // true
console instanceof Object // true
isPlainObject(console) // false
So you either check if Object.prototype is the immediate [[Prototype]]
or create a long list of constructors to test against. That list will go out of date very quickly given the variety of host environments available and the freedom for implementors to extend it. Also, you need to test every member of the host object set before trying to use it as it may not exist for the particular host on which the code is running.
It is not quicker, but more precise, with a check for falsy values, like null
, which is an object.
function isPlainObject(input) {
return input && !Array.isArray(input) && typeof input === 'object';
}