There are multiple ways to detect whether an Object has a property. You’d think it’d be as easy as myObject.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 same falsy
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 to Boolean
. The Boolean
will cast true
for truthy values. Even things such as undefined
and null
(both falsy values, !!null
is false
when cast to Boolean
). 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 empty Array
is an example of a truthy value:
var a = []; // []
What if we want to convert it to a Boolean
though? It’s truthy, so we should expect true
:
var a = !![]; // true
null
is an example of a falsy value:
var a = null; // null
And the expected output of false
:
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’s prototype
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 casts values, the value is null
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.
Free eBook
Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.
- Observables and Async Pipe
- Identity Checking and Performance
- Web Components <ng-template> syntax
- <ng-container> and Observable Composition
- Advanced Rendering Patterns
- Setters and Getters for Styles and Class Bindings
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?
Using myObject.hasOwnProperty('prop')
is a great way of accessing the Object’s keys directly, which does not look into the Object’s prototype
- 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 the hasOwnProperty
method completely as it’s painful with host
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 the Object.prototype
directly to guarantee any hasOwnProperty
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 of hasOwnProperty
(take that, IE) and ensure we’ve the exact hasOwnProperty
we want from the Object.prototype
.
Obviously you’d want to wrap it inside a helper function or something to save writing out that prototype
each time:
function hasProp (obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
if (hasProp(toddObject, 'favouriteDrink')) {}
‘prop’ in myObject
The in
operator isn’t so widely used as the former methods, but is probably worth using after reading this. It also returns a Boolean
much like !!myObject
, but does not evaluate the value, it evaluates the existence of the property!. This means if a property has a value of false
, we get a correct reading that the property does infact exist.
var toddObject = {
name: 'Todd',
favouriteDrink: null,
cool: false
};
'cool' in toddObject; // true
The in
operator is probably your best friend for checking the existence of a property, it’s also pretty concise.
Gotchas
The in
operator also looks up the prototype
, 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 use typeof
as well.
What does it mean?
The standard typeof
operator returns a String
(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 =
) as null == undefined
anyway.
Gotchas
Only use it if you know what you’re doing as 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 the in
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
}
Thank you for reading!