The new method Object.hasOwn() returns a boolean indicating whether the specified object has the indicated property as its own property but so does Object.prototype.hasOwnProperty(), what is the difference between them and what is the benefit of using one over the other?
2 Answers
Using Object.hasOwn() as a replacement for Object.hasOwnProperty()
Object.hasOwn() is intended as a replacement for Object.hasOwnProperty() and is a new method available to use (yet still not fully supported by all browsers like safari yet but soon will be)
Object.hasOwn() is a static method which returns true if the specified object has the specified property as its own property. If the property is inherited, or does not exist, the method returns false.
const person = { name: 'John' };
console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false
console.log(person.hasOwnProperty('name'));// true
console.log(person.hasOwnProperty('age'));// false
const person2 = Object.create({gender: 'male'});
console.log(Object.hasOwn(person2, 'gender')); // false
console.log(person2.hasOwnProperty('gender')); //false
// gender is not an own property of person, it exist on the person2 prototype
So, after looking at both Object.hasOwn() and Object.hasOwnProperty() in action, they seem quite the same.. So why should we use Object.hasOwn() over the Object.hasOwnProperty()?
It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it's possible to solve these kind of problems by calling Object.prototype.hasOwnProperty.call(<object reference>, <property name>) on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)
let person = {
hasOwnProperty: function() {
return false;
},
age: 35
};
console.log(Object.hasOwn(person, 'age')); // true
console.log(person.hasOwnProperty('age')); // false
let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
console.log(person.age); // true - works regardless of how the object was created
}
if (person.hasOwnProperty('age')){ // throws error - person.hasOwnProperty is not a function
console.log('hasOwnProperty' + person.age);
}
More about Object.hasOwn can be found here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
Browser compatibility - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility
7 Comments
hasOwn() needs node16... if you have node-dependent 'stuff'. E.g., Postman Monitors' node version is not yet up to this version, so any Monitor test runs will fail, even though hasOwn() works locally. (EDIT: Thinking it's their node, since we updated node in Newman to work around this, but I digress...). So that's something to think about when choosing hasOwn(). Cheers.TLDR: hasOwn() is a new and fixed version of hasOwnProperty(). Use hasOwn() where you would want to use hasOwnProperty().
hasOwn() is a static method of Object. Usage: Object.hasOwn(myObj, 'myProp'))
hasOwnProperty() is a method of Object instances. Usage: myObj.hasOwnProperty('myProp')
Note: Object.hasOwn() is recommended over hasOwnProperty(), in browsers where it is supported.
Note: Object.hasOwn() is intended as a replacement for Object.prototype.hasOwnProperty().
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn
If the tested object is under your control and you don't do unrecommended changes to it, both methods behave identically.
Example "as expected", showing identical results for normal objects for all possible cases:
const mySuperObj = {
mySuperProp: 'Property defined in the prototype of myObj.',
};
const myObj = Object.create(mySuperObj);
myObj.myProp = 'Property defined directly on myObj.'
console.log(myObj.myProp, 'Expected output: true'); // "Property defined directly on myObj."
console.log(myObj.hasOwnProperty("myProp")); // true
console.log(Object.hasOwn(myObj, "myProp")); // true
console.log('Method existing on a prototype of myObj. Expected output: false');
console.log(myObj.hasOwnProperty("toString")); // false
console.log(Object.hasOwn(myObj, "toString")); // false
console.log(myObj.mySuperProp, 'Expected output: false'); // "Property defined in the prototype of myObj."
console.log(myObj.hasOwnProperty("mySuperProp")); // false
console.log(Object.hasOwn(myObj, "mySuperProp")); // false
console.log('Property does not exist on myObj nor its prototype. Expected output: false');
console.log(myObj.hasOwnProperty("undeclaredPropertyValue")); // false
console.log(Object.hasOwn(myObj, "undeclaredPropertyValue")); // false
Two cases (four variants) where the hasOwnProperty() could fail with possibly unexpected result:
- the inherited hasOwnProperty() method is overridden
- the object is a null-prototype object and so it does not inherit from Object.prototype the method hasOwnProperty()
Example "unexpected case 1", showing different results for objects which were messed with (read comment in code snippet):
// When you are unaware they have decided to override hasOwnProperty() method
const someCrazyFramework = {
hasOwnProperty() {
return false;
},
myProp: "Property defined directly on myObj.",
};
console.log('***', someCrazyFramework.myProp, 'Expected output: true'); // "Property defined directly on myObj."
console.log('hasOwnProperty():', someCrazyFramework.hasOwnProperty('myProp')); // false (possibly unexpected)
console.log('hasOwn():', Object.hasOwn(someCrazyFramework, 'myProp')); // true
// There is a workaround for hasOwnProperty(), but it's unintuitive and it's also not 100% reliable:
console.log('***', someCrazyFramework.myProp, 'Using workaroud. Expected output: true'); // "Property defined directly on myObj."
// Use the hasOwnProperty property from the Object prototype
console.log('hasOwnProperty() with a workaround1:', Object.prototype.hasOwnProperty.call(someCrazyFramework, 'myProp')); // true
// Use another Object's hasOwnProperty and call it with 'this' set to someCrazyFramework
console.log('hasOwnProperty() with a workaround2:', ({}).hasOwnProperty.call(someCrazyFramework, "myProp")); // true
Object.prototype.hasOwnProperty = () => 'we broke it';
console.log('hasOwnProperty() with a workaround1, after more messing with the object:', Object.prototype.hasOwnProperty.call(someCrazyFramework, 'myProp')); // 'we broke it' (possibly unexpected)
console.log('hasOwnProperty() with a workaround2, after more messing with the object:', ({}).hasOwnProperty.call(someCrazyFramework, "myProp")); // 'we broke it' (possibly unexpected)
Example "unexpected case 2", showing different results for objects which were messed with (read comments in code snippet):
// variant A, creating null-prototype object
const myObjA = Object.create(null);
myObjA.myProp = "exists";
// variant B, using the object initializer syntax with __proto__: null
const myObjB = {
myProp: "defined property",
__proto__: null,
};
// variant C, change the prototype of an existing object to null by calling setPrototypeOf() method
const myObjC = {
myProp: "defined property",
};
Object.setPrototypeOf(myObjC, null);
console.log('hasOwn():', Object.hasOwn(myObjA, "myProp")); // true
console.log('hasOwnProperty():', myObjA.hasOwnProperty("myProp")); // Uncaught TypeError: foo.hasOwnProperty is not a function
// the rest will not be executed after the Error, but the results are the same and what comments show.
console.log('hasOwn():', Object.hasOwn(myObjB, "myProp")); // true
console.log('hasOwnProperty():', myObjB.hasOwnProperty("myProp")); // Uncaught TypeError: foo.hasOwnProperty is not a function
console.log('hasOwn():', Object.hasOwn(myObjC, "myProp")); // true
console.log('hasOwnProperty():', myObjC.hasOwnProperty("myProp")); // Uncaught TypeError: foo.hasOwnProperty is not a function
Note: Why this similar answer to the other one: I spent some time comprehending the other answer and understanding the examples. I did not know right away if there are different results for "normal" Object and what are those cases where there are different cases, when and why could they be encountered. Also, the workaround does not really help. If an object is messed with, they could mess with its prototype for the same un-reason too. see example "unexpected case 1".
Source: MDN, three links in this post