Methods to determine if an Object has a given property
There are multiple ways to detect whether an Object has a property. You’d think it’d be as easy asmyObject.hasOwnProperty('prop');
- but no, there are a few different ways with their own problems and gotchas. Let’s look at the few ways to check property existence, concepts that confuse JavaScript developers, prototype chain lookups and problems JavaScript might provide us.
⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
Table of Contents
⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
Double bang !! property lookup
We’ve all seen it, probably in something such as Modernizr for simple feature detection, the infamous!!
amongst our JS. Important note before we begin this one, it doesn’t actually check if an Object has a property “as such”, it checks the_value_of the Object property. Which means if the property value is false, or the object property doesn’t even exist, they give the samefalsy
result - which can be really bad if you use it without knowing what it does and its limitations.
What does it mean?
The double-bang is a simple way to typecast something toBoolean
. TheBoolean
will casttrue
fortruthy_values. Even things such asundefined
andnull
(both falsy values,!!null
isfalse
when cast toBoolean
). The_absolute key_here is that it casts_values. I’ll say it again,values! This is irrelevant to the shape and size of your Object. We convert truthy and falsy values to Boolean.
Examples
An emptyArray
is an example of a_truthy_value:
var a = []; // []
What if we want to convert it to aBoolean
though? It’s truthy, so we should expecttrue
:
var a = !![]; // true
null
is an example of a_falsy_value:
var a = null; // null
And the expected output offalse
:
var a = !!null; // false
This means that we can use it when looking up our Objects!
var toddObject = {
name: 'Todd',
cool: false
};
!!toddObject.name // true (correct result as it's a truthy value)
This method also looks up the Object’sprototype
chain to see if the property exists, which can cause unintended side effects if naming of properties is the same as a prototypes.
// Object.prototype.toString
!!toddObject.toString // true
// !!Array.prototype.forEach
!![]['forEach'] // true
Gotchas
Beware of using it for detecting your own Objects. We often create Objects and defaults such as this:
var toddObject = {
name: 'Todd',
favouriteDrink: null
};
If we’re using the double-bang to check if an Object property exists using this method, then it’s definitely a silly idea:
var toddObject = {
name: 'Todd',
favouriteDrink: null
};
if (!!toddObject.favouriteDrink) { // false
// do something if it exists, I think...
}
That would be naive! The above code (to the new developer or non-double-banger) might say“If toddObject.favouriteDrink exists, do something”. But no, because (I’ll say it again…) this castsvalues, the value isnull
and falsy - even though the property exists. It’s generally not a good idea in this case to use it for checking if a property exists incase it has a falsy value to begin with.
⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
hasOwnProperty
We went as far as getting a native method for this, but it’s not 100% reliable for a few reasons. Let’s examine it first.
What does it mean?
UsingmyObject.hasOwnProperty('prop')
is a great way of accessing the Object’s keys directly, which_does not_look into the Object’sprototype
- hooray, this is great for specific use cases.hasOwnProperty
returns a Boolean for us on whether a property exists.
Examples
var toddObject = {
name: 'Todd',
favouriteDrink: null
};
if (toddObject.hasOwnProperty('favouriteDrink')) { // true
// do something if it exists, fo sho
}
But don’t be sold on this exact implementation… read below for best practice.
Gotchas
IE messes up thehasOwnProperty
method completely as it’s painful withhost
Objects (host objects don’t have the hasOwnProperty method).
JavaScript also decided not to protect the method’s name, so we can infact do this:
var toddObject = {
hasOwnProperty: 'hello...'
};
This makes it hard to fully trust it. What we can do however is access theObject.prototype
directly to guarantee anyhasOwnProperty
calls haven’t been tampered with or overridden.
Let’s bulletproof the process:
var toddObject = {
name: 'Todd',
favouriteDrink: null
};
if (Object.prototype.hasOwnProperty.call(toddObject, 'favouriteDrink')) { // true
// do something if it exists, fo sho sho!
}
The secret sauce here is.call()
to change the context ofhasOwnProperty
(take that, IE) and ensure we’ve the exacthasOwnProperty
we want from theObject.prototype
.
Obviously you’d want to wrap it inside a helper function or something to save writing out thatprototype
each time:
function hasProp (obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
if (hasProp(toddObject, 'favouriteDrink')) {}
⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
‘prop’ in myObject
Thein
operator isn’t so widely used as the former methods, but is probably worth using after reading this. It also returns aBoolean
much like!!myObject
, but does not evaluate the value, it evaluates the existence of the property! This means if a property has a value offalse
, we get a correct reading that the property does in fact exist.
var toddObject = {
name: 'Todd',
favouriteDrink: null,
cool: false
};
'cool' in toddObject; // true
Thein
operator is probably your best friend for checking the existence of a property, it’s also pretty concise.
Gotchas
Thein
operator also looks up theprototype
, which_may_cause unintended side effects:
// inherits Object.prototype.toString
'toString' in toddObject; // true
But we should know these property names and not create conflicts, right ;)
typeof
We can usetypeof
as well.
What does it mean?
The standardtypeof
operator returns aString
(not a very reliable one), and we can evaluate it against something, such as!== 'undefined'
- which indicates it exists.
if (typeof toddObject.name !== 'undefined') {
// do something
}
It looks a little ugly, as well as being quite long to write out if we were to make multiple checks using this method. Also,null
would fall under this check unless using!= 'undefined'
(single=
) asnull == undefined
anyway.
Gotchas
Only use itif you know what you’re doingas it’s very unreliable for standard type checking.
⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
Feature detection
I can’t recall exactly what was said, but someone (I think) once told me that some vendor once implemented a feature with a falsy value if it didn’t exist (though I’m not even certain that’s true, worth a mention though)… and as such thein
operator is best for these such cases:
// just an example, not the one somebody mentioned...
if ('draggable' in document.createElement('div')) {
// do something if prop exists
}