What’s the deal with Object.prototype.hasOwnProperty.call()?

Photo by Shaojie on Unsplash

I am sure you might have seen the following line of code either while reading someone’s code or in a library.

Object.prototype.hasOwnProperty.call(objRef, ‘propName’);

And now you are wondering what on earth this code is doing. You start doubting your JavaScript skills. Don’t worry. You are at the right place. 😃

I have chosen this piece of code for a few purposes, and by demystifying this, we will understand the following things:

  1. What is Object.prototype?

If this sounds intriguing to you, let’s get started.

1. Object.prototype

Prototypal inheritance is one of the main pillars of JavaScript language which allows an object to inherit methods and properties on its prototype. You can think of the prototype as a template.

Prototypal inheritance allows an object to inherit methods and properties on its prototype.

It’s better to understand with an example:

var obj = {name: ‘aman’}
obj.hasOwnProperty(‘name’) // returns true

As you see, we haven’t defined any hasOwnProperty on our obj object but we managed to invoke it. How is it possible? 🤔

This is possible due to the prototypal inheritance and the way prototype chain works. Let’s dig a bit deeper.

When we created our literal object `obj`, its prototype was set to Object.prototype. To verify we can see:

Object.getPrototypeof(obj) === Object.prototype // returns true

[[Prototype]] is an inheritance relationship between objects. In our case, it’s the relation between the obj and Object’s prototype.

The prototype chain looks like:

// Prototype chain
obj — -> Object.prototype — → null

When we try to access a property on an object, the interpreter first looks for it on the object itself. If it couldn’t find the property on the object, it will traverse up until it finds the property in the chain.

Thus, when we invoked hasOwnProperty(), the interpreter couldn’t find it on the obj, so it traverses up in the chain and finds it on Object.prototype.

Additionally, We can set up or override the prototype chain however we want by using Object.setPrototypeOf() method or by using Object.create().

Consider this example:

var person = {name: ‘peter’};
var PersonPrototype = {getName: function(){ return this.name; }};
// Setting person’s prototype
Object.setPrototypeOf(person, PersonPrototype);
// Trying to access getName() method will cause a prototype chain lookup (aka prototype delegation)
// and finds it on PersonPrototype.
person.getName(); // ‘peter’

2. Borrowing a function

Let’s imagine If I have the following function and an object:

function sayHello() { console.log(`Greetings ${this.name}`) }
var person = {name: ‘peter’};

How would you make the object personborrows sayHello, and invoke the correct name in the greetings? We don’t want person to implement sayHelloor have it anywhere on its prototype chain. 🤔

The answer is via call and applymethod available on Function.prototype.

In JavaScript, every function we create inherits from Function.prototype.
And as we have just learned that via prototype chain, we can use the callmethod on all function objects. 💡

In JavaScript, every function we create inherits from Function.prototype.

The syntax of the call method is:

// ‘call’ method is available on Function.prototype
func.call(objRef, …args);

The first argument is an object who wants to borrow this function followed by the list of arguments for that function.

So, for personto borrow sayHello, all we have to do is use call method on sayHellopassing personas an argument:

sayHello.call(person); // Greetings peter

3. Object.prototype.hasOwnProperty vs instance.hasOwnProperty

After a lightweight tutorial on Prototypal inheritance and borrowing functions, finally, it’s time to demystify why one would use hasOwnProperty on the Object.prototype and not on the object instance.

As we mentioned above that we can control the prototype chain ourselves. One way is to use Object.create() method while creating an Object instance.

// Object.create() accepts an argument which becomes
// the prototype for newly created object.
var a = Object.create(null); // Setting `null` as prototype for ‘a’.
// Adding a ‘name’ property on the instance
a.name = ‘peter’;
// Using `hasOwnProperty` method would cause an error
a.hasOwnProperty(‘name’); //🚫 throws a TypeError: a.hasOwnProperty is not a function

Trying to invoke hasOwnProperty throws an error as there’s no such method available on the object or its prototype chain. The prototype chain was like:

// Prototype chain
a — -> null

You may be wondering why someone would create an object like this. But the irony is that in JavaScript you are allowed to be as crazy as you want 🔥.

Imagine you are creating a library and exposing a function that accepts an object as an argument. If your function makes use of hasOwnProperty directly on the object being passed from outside, it could break your code if someone passes an object with `null` as its prototype.

Consequently, to guard this problem we can use the function borrowing technique we previously learned. The passed-in object argument can borrow hasOwnProperty available on Object.prototype as we previously learned via the call method 🚀😇.

// Will not break your code if ‘a’ has a null prototype. ✅
Object.prototype.hasOwnProperty.call(a, ‘name’); // true;

Summary

  • Every object literal inherits from Object.prototype. This allows you to invoke some of the methods available like hasOwnProperty.

That’s all for now. I hope you have enjoyed reading this article and learned a few things. Go and share this achievement with others 😍.

Developer @ Domain Sydney. Tech enthusiast and a pragmatic programmer. If coding is hard, you are not doing it right.