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.