JavaScript: hasOwn() — new way to check if Object has property
Before ECMAScript 2022 (ES13)
There were 2 traditional ways to check if JS object has any custom property:
const developer = {
age: 32
};
'age' in developer; // true
developer.hasOwnProperty('age'); // true
The main difference is that in
checks both: custom properties of the object but also all inherited ones from its prototype chain. Whereas hasOwnProperty()
— checks only the object itself.
For example, as you know — all JS objects are extended from the Object
base class, which has constructor
property. Thus 2 methods will return different results:
'constructor' in developer; // true
developer.hasOwnProperty('constructor'); // false
hasOwnProperty()
besides focusing only on custom object properties also omits getters and setters.
In 90% scenarios hasOwnProperty()
is more preferable to use. But it has its own risks.
“hasOwnProperty” limitations
hasOwnProperty
may be overwritten:
const developer = {
age: 32,
hasOwnProperty: 'frontend'
};
developer.hasOwnProperty('age') // throws a TypeError
It also may cause security issues. A specific example of this is when a web server reads in JSON data from a client and uses the hasOwnProperty
property on that object. A problem could happen if client sends malicious JSON value like {"hasOwnProperty": 1}
that would cause the server to fail.
2. If you create new object with help of create(null)
function, then newly created object doesn’t inherit from Object.prototype
, so it doesn't have hasOwnProperty
method.
const developer = Object.create(null);
someObject.hasOwnProperty('age'); // throws a TypeError
Use case for create(null)
instead of simple curly braces {}, is when you want to create objects that will be used as a Map.
Workaround for “hasOwnProperty”
To avoid bugs like this, it’s better to always call these methods from Object.prototype
. For example, foo.hasOwnProperty('bar')
should be replaced with Object.prototype.hasOwnProperty.call(foo, 'bar')
.
/* not recommended */
const hasBarProperty = developer.hasOwnProperty('age');
/* recommended */
const hasBarProperty = Object.prototype.hasOwnProperty.call(developer, 'age');
But this looks like a syntax overkill, isn’t it?
ES13 “hasOwn()” method for rescue
Since ECMAScript 2022 there is no need to use that ugly one-liner, as we can use the new built-in Object.hasOwn()
method.
It returns true
if the specified object has the indicated property as its own one. Even if the property value is null
or undefined!
If the property is inherited or does not exist — then the method returns false
.
const developer = {
age: 32
};
Object.hasOwn(developer, 'age') // true
Object.hasOwn(developer, 'not-existing-property'); // false
Object.hasOwn(developer, 'constructor'); // false
Now even if hasOwnProperty
is overwritten, we still may be sure that our properties check will return the correct result:
developer.hasOwnProperty = () => false;
developer.hasOwnProperty('age'); // false
Object.hasOwn(developer, 'age') // true
Basically these lines below are doing the same job:
Object.prototype.hasOwnProperty.call(developer, 'age'); // true
Object.hasOwn(developer, 'age'); // true
But look how more intuitive it is. Worth mentioning that MDN recommends to useObject.hasOwn()
over hasOwnProperty()
, in browsers where it is supported.
Platforms compatibility:
Luckily for us, the Object.hasOwn()
syntax looks simple and attractive. Thus, all the major browsers together with server environments support it
Conclusion
The use of Object.hasOwn()
versus hasOwnProperty()
has a number of benefits: it’s more concise and readable, but also solves the hasOwnProperty()
limitations.
It’s a simple change that can have a big impact on the overall quality of the code and will make the life of your colleagues easier, while reading your pull requests :)