Determining if an object property exists
One of the most basic tests developers perform in JavaScript is whether or not a particular property exists on an object. Since feature detection is the preferred method of code forking, developers are encouraged to test for the existence of properties before using them. There is a lot of buggy JavaScript code out there as inexperienced developers try to use feature detection. A lot of the problems reside with a lack of understanding as to the nature of object properties in JavaScript.
Where do properties come from?
Before attempting to detect properties, it’s important to understand from where they originate. There are two basic types of properties in JavaScript: those that exist on the object (also known as “own” properties) and those that are inherited through the prototype chain (often called “prototype” properties). Consider the following:
var person = {
name: "Nicholas"
};
alert(person.name); //"Nicholas"
alert(person.toString()); //"[object Object]"
In this code, the object person
has only one own property, which is name
. You can still access other methods on the object such as toString()
, but these are inherited through the prototype chain. Object literals inherit from the Object
type, so all of the basic methods of Object
are accessible on the instance.
The big difference between own properties and prototype properties is the difference between unique and shared values. Own properties belong to that single object instance and can’t be affected by other instances of the same type; prototype properties belong to the prototype of the object, and since the prototype can be shared amongst multiple instances, these properties are also shared amongst multiple instances. Here’s another example:
var person2 = Object.create(person);
var person3 = Object.create(person);
alert(person2.name); //"Nicholas"
alert(person3.name); //"Nicholas"
person.name = "Adam";
alert(person2.name); //"Adam"
alert(person3.name); //"Adam"
This example uses the <a href="http://javascript.crockford.com/prototypal.html">Object.create()</a>
method from ECMAScript 5 to create two objects, person2
and person3
, that inherit from person
. The prototype for both person2
and person3
is person
, and so name
is actually a prototype property that is accessible through person2
and person3
. This is why displaying the values of name on both objects results in the same value: they are both sharing the prototype property name
. That means when person.name
is changed directly, the change is accessible from the instances.
It’s important to understand that name
is a prototype property for both person2
and person3
, but it’s an own property for person
. You can only assign values to own properties, so attempting to assign a value to a prototype property actually causes a new own property of the same name to be created. Example:
alert(person2.name); //"Nicholas"
alert(person3.name); //"Nicholas"
person2.name = "Adam";
alert(person2.name); //"Adam"
alert(person3.name); //"Nicholas"
Since you can’t assign to prototype properties, assigning a new value to person2.name
actually creates a new own property on person2
called name
. Own properties always shadow prototype properties, so the next time you access person2.name
, you’re accessing the own property instead of the prototype property. That will continue until the own property is removed using delete
, such as:
delete person2.name;
alert(person2.name); //"Nicholas"
You can only call delete
on an own property to remove it (calling on a prototype property does nothing). Once the own property name
is removed, there is nothing shadowing the prototype property name
and so person2.name
now refers to the prototype property.
Note: While all native object types (Array
, Boolean
, Date
, all Error
variants, Function
, Number
, RegExp
, and String
) inherit from Object
, non-native object types, such as those that represent the DOM in browsers, don’t necessarily inherit from Object
in all browsers.
Detecting properties
Let’s say you want to determine if a given object has a property of name. In experienced developers tend to write code like this:
//doesn't accurately test for existence
if (person.name){
//yay! property exists!
}
At first glance, this seems okay. However, understanding how JavaScript works reveals some problems with this approach. First, this will only succeed if the value of person.name
is truthy, meaning it’s an object, a non-empty string, a non-zero number that’s not NaN
, true
, and not null
or undefined
. That means if person.name
is the empty string (“”), this check will fail. Failing, in this case, doesn’t mean that the property doesn’t exist. In fact, the property does exist and contains a value, but the value is falsy and so doesn’t pass this test.
Detecting own properties
Keeping in mind that this is about testing for the existence of the property and not for the usability or data type, there are a couple of options. The first option is to detect own properties, and it comes via a method on the Object
type called hasOwnProperty()
. Since native objects inherit from Object
, this property is inherited by these objects and can be used to detect the existence of own properties:
alert(person.hasOwnProperty("name")); //true
alert(person2.hasOwnProperty("name")); //false
person2.name = "Adam";
alert(person2.hasOwnProperty("name")); //true
delete person2.name;
alert(person2.hasOwnProperty("name")); //false
Initially, person2
has a prototype property name
, so hasOwnProperty()
returns false. Once an own property is created, calling hasOwnProperty()
returns true. And after the property is removed via delete
, this method again returns false.
JSON serialization works only for own properties, and non-native JSON serialization utilities used hasOwnProperty()
to ensure that only the properties defined on object literals were included in the resulting string.
Detecting all properties
If you only care that the object has a property and don’t care whether it’s an own property or a prototype property, you can use the in
operator to determine the existence of the property. Example:
if ("name" in person){
//property exists
}
The in
operator returns true when the named property exists on the object. In many cases, the in
operator is all that you’ll need (especially when dealing with DOM objects). In fact, Mark Pilgrim’s All-In-One Almost-Alphabetical No-Bullshit Guide to Detecting Everything for HTML5 makes extensive use of in
for detecting the new HTML5 features on DOM objects.
Conclusion
If you just want to check for the existence of properties, and not necessarily what their value might be, then you have two safe options: hasOwnProperty()
and the in
operator. The hasOwnProperty()
property method should be used if you want to detect own properties only. If you want to test property existence and don’t care if it’s an own property or an object property, then the in
operator is the one to use.
Update (27 July 2010): Added false
and NaN
to list of falsy values.****
Update (29 July 2010): Fixed description of truthy/falsy values.
Update (22 December 2012): Fixed link to Mark Pilgrim’s list.