An important task in JavaScript development is to check if a property has already been assigned a value. There are two ways to check for the presence of a property in an object. The first method, prop in obj
, checks the existence of the property in the object or in its prototype chain. The second method, obj.hasOwnProperty(prop)
, checks if the property exists on the object itself.
If a property exists on the object’s prototype, it is masked by an assignment of that property on the object itself. Consider the following code snippet:
(function () {
var p = {
name : "human",
};
var a = Object.create(p);
console.log(a.name); // human
console.log(a.hasOwnProperty("name")); // false
a.name = "Ali";
console.log(a.name); // Ali
console.log(a.hasOwnProperty("name")); // true
})();
Noting these results, it would seem appropriate to use hasOwnProperty
as a test for checking whether the property has been assigned a value on the object proper. But this leads to an unexpected result in the particular case of “accessor” properties:
(function () {
var p = Object.defineProperties({
_age : 0,
}, {
_age : {
enumerable : false,
},
age : {
get : function () {
return this._age;
},
set : function (age) {
if (isNaN(age) || (age < 0)) {
throw new Error("Invalid value for age: " + age);
}
this._age = age;
},
enumerable : true,
configurable : true,
},
});
var a = Object.create(p);
console.log(a.age); // 0
console.log(a.hasOwnProperty("age")); // false
a.age = 14;
console.log(a.age); // 14
console.log(a.hasOwnProperty("age")); // false
})();
This example shows that “accessor” properties of the prototype are not masked by value assignment on the descendent object. Consequently, hasOwnProperty
cannot detect value assignment in these cases.