Bisexual Pride

For a long time, the Object.prototype.hasOwnProperty() method was the standard way to check if an object had a property as its own property (as distinct from an inherited property) in JavaScript. However, the newer Object.hasOwn() method works in situations where the older method doesn’t.

The Object.prototype.hasOwnProperty() method

All objects (except those will a null prototype) inherit the Object.prototype.hasOwnProperty() method from their prototype chain. You can invoke this method on any such Object instance.

let hedgehog = {
name: "sonic",
color: "blue",
};

hedgehog.hasOwnProperty("color"); // true
hedgehog.hasOwnProperty("toString"); // false

The object referenced by the hedgehog variable has two of its own properties: .name and .color. When we invoke hedgehog.hasOwnProperty("color"), the return value is true, because .color is one of the object’s own properties.

When we invoke hedgehog.hasOwnProperty("toString"), the return value is false. Although the object inherits the Object.prototype.toString() method from its prototype (Object.prototype), it isn’t one of the object’s own properties.

The Object.hasOwn() method

The Object.hasOwn() method works almost identically to the Object.prototype.hasOwnProperty() method. The only difference is that you invoke it directly on Object, not on an Object instance. In other words, it’s a static method instead of an instance method. You pass in the Object instance as the first argument and the property name as the second argument.

let hedgehog = {
name: "sonic",
color: "blue",
};

Object.hasOwn(hedgehog, "color"); // true
Object.hasOwn(hedgehog, "toString"); // false

The Object.hasOwn() method works in two situations where the Object.prototype.hasOwnProperty() method doesn’t:

  1. Objects with a null prototype.
  2. Objects that override (shadow) the Object.prototype.hasOwnProperty() method.

Objects with a null prototype

When you create an object literal with the object initializer syntax, the object referenced by the Object.prototype property becomes the prototype of the new object (unless you specify a different object via the __proto__ key). We can use the Object.getPrototypeOf() method to confirm this.

let hedgehog = {
name: "sonic",
color: "blue",
};

Object.getPrototypeOf(hedgehog) === Object.prototype; // true

The prototype of the object referenced by the Object.prototype property is null, marking the end of the prototype chain. We can still invoke the Object.prototype.hasOwnProperty() on this object because it’s one of the object’s own properties.

Object.getPrototypeOf(Object.prototype) === null; // true
Object.prototype.hasOwnProperty("toString"); // true

However, it’s also possible to create an object with a null prototype. You can either add a __proto__ key using the object initializer syntax or invoke the Object.create() method.

let x = { __proto__: null };
Object.getPrototypeOf(x) === null; // true

let y = Object.create(null);
Object.getPrototypeOf(y) === null; // true

Because the objects referenced by the x and y variables don’t inherit from Object.prototype, they don’t have access to the Object.prototype.hasOwnProperty() method. If you try to invoke it, the JavaScript interpreter will throw a TypeError.

x.hasOwnProperty("prop"); // TypeError: x.hasOwnProperty is not a function
y.hasOwnProperty("prop"); // TypeError: y.hasOwnProperty is not a function

Note that this is also a problem for objects that inherit from an object with a null prototype. Even though these objects’ prototype isn’t null, Object.prototype still doesn’t appear anywhere in their prototype chain, so they still don’t inherit from it.

let x = { __proto__: null };
let y = Object.create(x);

Object.getPrototypeOf(y) === x; // true
y.hasOwnProperty("prop"); // TypeError: y.hasOwnProperty is not a function

The Object.hasOwn() method solves this problem. Because the method is invoked directly on Object, and not on the Object instance (which doesn’t inherit from Object.prototype), it works as expected. No TypeError is thrown.

let x = { __proto__: null };
Object.hasOwn(x, "prop"); // false

let y = Object.create(null);
Object.hasOwn(y, "prop"); // false

Objects that override (shadow) the Object.prototype.hasOwnProperty() method

When an object overrides a property that it inherits from its prototype chain, it is said to shadow that property. The inherited property still exists in the prototype chain, but because of the way property lookup occurs, the JavaScript interpreter won’t search for it further up the chain once it’s been found.

let hedgehog = {
name: "shadow",
color: "black",
hasOwnProperty() {},
};

hedgehog.hasOwnProperty("color"); // undefined

The object referenced by the hedgehog variable has its own implementation of the .hasOwnProperty() method. Because the function body is empty, the method’s implicit return value is undefined. You might unwittingly use this method in your code, unaware that it shadows the Object.prototype.hasOwnProperty() method. Regardless of the function body, the point here is that you can’t rely on the Object.prototype.hasOwnProperty() method if an object has shadowed it. The Object.hasOwn() method solves this problem.

let hedgehog = {
name: "shadow",
color: "black",
hasOwnProperty() {},
};

Object.hasOwn(hedgehog, "color"); // true

The Function.prototype.call() method

It’s worth noting that you can use the Function.prototype.call() method to solve these problems too, but the Object.hasOwn() method is clearly more ergonomic.

let x = { __proto__: null };
Object.prototype.hasOwnProperty.call(x, "prop"); // false

let hedgehog = {
name: "shadow",
color: "black",
hasOwnProperty() {},
};

Object.prototype.hasOwnProperty.call(hedgehog, "color"); // true

Summary

The Object.hasOwn() method is intended as a replacement for the Object.prototype.hasOwnProperty() method. The former works in two situations where the latter doesn’t: on objects with a null prototype and on objects that shadow the Object.prototype.hasOwnProperty() method. However, the Object.hasOwn() method has only been around since Chrome 93 / Firefox 92 / Safari 15.4, while the Object.prototype.hasOwnProperty() method dates all the way back to IE 6. Keep this in mind if browser support is an issue.