How do you check if a value is an object in JavaScript?
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:
v
is '[object Object]'
.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'}))))