Mastering hasOwnProperty
in JavaScript: Why and How to Use Object.prototype.hasOwnProperty.call()
JavaScript is a prototype-based language that offers great flexibility, but this very feature can also present challenges for beginners. In this article, we’ll dive into the details and explore these concepts with clear examples
Object.prototype.hasOwnProperty.call
is a pattern used to check if an object has a specific property directly on the object (not in its prototype chain). Let's break down how it works and why it's used.
Breakdown of Object.prototype.hasOwnProperty.call
Object.prototype.hasOwnProperty
:
hasOwnProperty
is a method that belongs toObject.prototype
. It is a built-in JavaScript method that checks whether the object itself has a specific property (not inherited through its prototype chain).- It returns
true
if the object has the property, andfalse
otherwise.
Example:
const obj = { key: 'value' };
console.log(obj.hasOwnProperty('key')); // true
console.log(obj.hasOwnProperty('nonExistentKey')); // false
.call():
.call()
is a method available to all JavaScript functions. It allows you to invoke a function, but you can specify the value ofthis
explicitly, and you can also pass additional arguments.- The first argument passed to
.call()
is the value ofthis
in the function call. In this case, we are usingObject.prototype.hasOwnProperty.call
to callhasOwnProperty
on a specific object, while ensuring the context (this
) is set to that object.
Example of .call()
:
function greet() {
console.log(this.message);
}
const obj = { message: 'Hello, World!' };
greet.call(obj); // Hello, World!
Why `Object.prototype.hasOwnProperty.call
?`
The reason we use Object.prototype.hasOwnProperty.call()
instead of directly calling hasOwnProperty()
on an object is to avoid issues with objects that may have overridden the hasOwnProperty
method.
The Problem
If an object has its own hasOwnProperty
method, it could override the original method on Object.prototype
. This means calling obj.hasOwnProperty()
might not work as expected.
Example:
const obj = {
hasOwnProperty: function() {
return false;
},
key: 'value'
};
console.log(obj.hasOwnProperty('key')); // false, because it's overridden!
In this case, obj.hasOwnProperty()
will return false
, even though the object does have the key
property.
The Solution
By using Object.prototype.hasOwnProperty.call()
, we bypass the object's own hasOwnProperty
method and ensure that we are using the original hasOwnProperty
from Object.prototype
, which reliably checks if the property is directly on the object.
Syntax
Object.prototype.hasOwnProperty.call(obj, 'propertyName');
obj
: The object on which you want to check if a property exists.'propertyName'
: The name of the property you're checking for.
Example
const obj = {
hasOwnProperty: function() {
return false; // This is intentionally overriding the default behavior
},
key: 'value'
};
// Using the pattern to check for the property
const hasKey = Object.prototype.hasOwnProperty.call(obj, 'key');
console.log(hasKey); // true, because we are using the correct `hasOwnProperty` method
In this example, even though obj
has its own hasOwnProperty
method that always returns false
, Object.prototype.hasOwnProperty.call()
will still return true
because it checks if key
exists directly on obj
, not affected by the object's own method.
Why Is This Useful?
- Safety: It ensures that you are calling the original
hasOwnProperty()
method fromObject.prototype
, which avoids any unexpected behavior caused by objects that overridehasOwnProperty
. - Prototype Chain:
hasOwnProperty()
checks if the property exists directly on the object (not its prototype chain). If you want to exclude inherited properties and only check for properties that are directly defined on the object itself, this is the method to use. - Commonly Used in Loops: This is especially useful when iterating over objects, like in
for...in
loops, where the object might inherit properties from its prototype chain. UsinghasOwnProperty
helps you distinguish between properties that belong to the object itself and properties that come from the prototype.
Example in Practice:
Consider an object that might have properties from both its prototype and its own properties:
const proto = { inheritedProp: 'I am inherited' };
const obj = Object.create(proto);
obj.ownProp = 'I am own property';
for (let key in obj) {
// Without hasOwnProperty, this will log both the own and inherited properties
console.log(key);
}
console.log('-----');
// Using hasOwnProperty to only log the own properties
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
console.log(key);
}
}
Output
inheritedProp
ownProp
-----
ownProp
In this case, the hasOwnProperty.call()
method ensures that only ownProp
is logged, and not the inherited property inheritedProp
from the prototype.