Mastering Prototypal Inheritance in JavaScript: A Comprehensive Guide
Understanding Prototypal inheritance in Javascript is the key concept to understand how objects really work in Javascript which has always been tricky when compared to other traditional OOPS patterns in different programming languages. Prototypal inheritance is a way in which our objects in JS can inherit properties/methods from other objects.
This is one of the most commonly asked questions in Senior Frontend Interviews
Let’s first go through a code snippet and understand it —
//We have an object `person1` with two properties `name` and `place`
const person1 = {
name: "bob",
place: "Amsterdam"
}
// we have another object `person2` with property `name`
const person2 = {
name: "john"
}
console.log(person2.name) // john
console.log(person2.place) // undefined
The above code snippet is pretty clear about how we created two different objects while logging person2.place
we get undefined
which is correct and expected, let’s add something magical to the above code -
person2.__proto__ = person1
console.log(person2.place) // Amsterdam
WHAT? Now we’re getting Amsterdam
a value of person2.place
that was never defined by us earlier. So, what’s going on here?
Let’s confirm if there’s any property place
existing in person2
the object via hasOwnProperty
the method —
console.log(person2.hasOwnProperty("place")) // false
So, what’s really going on here? We do not have any place
property defined in the person2
object but still, it’s returning a value when we’re trying to access it.
If you remember we wrote a magical line person2.__proto__ = person1
and this is where everything happened, now let's understand how.
Understanding Prototypal Inheritance in Javascript
In Javascript, all the objects have a hidden property [[Prototype]] which either stores null
within it or stores references to another object, and then we’ve another method __proto__
(proto property) which is a getter/setter of the hidden [[Prototype]]
property of the object.
Whenever we try to fetch any property/method from any object, it has a default tendency to look over its own property, and if not found it checks within its [[Prototype]]
property and returns the value. This is why we were able to get place
property inside person2
object which was originally defined inside person1
object.
Let’s verify our concept and try to console person2
—
We can clearly see in the above image that we’ve [[Prototype]] object inside person2
which stores the reference of person1
object created earlier.
Prototype Chain
You might be wondering why is there another [[Prototype]]
property inside the [[Prototype]]
property of person2
object. And first of all, what's this [[Prototype]]
in the object that we never defined?
This is the concept of a prototype chain in which an object looks over its [[Prototype]]
to fetch the property/method and if not found it iterates to the [[Prototype]]
of its own [[Prototype]]
and if again not found it goes on till it finds the null
.
Isn’t it confusing, let’s understand by another example —
let animal = {
eats: true
};
let rabbit = {
jumps: true,
__proto__: animal
};
let kangaroo = {
swims: true,
__proto__: rabbit
}
console.log(kangaroo.eats) // true
This is how chained prototypal inheritance looks like when consoled out —
Things to note about Prototypal Inheritance in object
- The reference of the prototype can’t be like a loop, like creating a circle. Javascript will throw an error if we try to assign
__proto__
in a circle. - The value of
__proto__
can be either an object ornull
. Other types are ignored. - An object can only have a single
[[Protype]]
property within it, it never inherits from two objects at the same time. - Prototype chaining ends only when it encounters
null
, or else it’ll go to the n level of depth to the top finding the requested property in the object. - An object always looks first within itself to search for any property before looking to its
[[Prototype]]
, if it gets the same property both within itself and[[Prototype]]
, it’ll give priority to its own property.
Creating prototypal inheritance using Object.create()
We already saw a way in which we can inherit the property defined in any object to another object via the __proto__
keyword. But we can do this in other ways too.
We can use Object.create() method to create any object and bind another object to its prototype. Let’s visualize how —
let animal = {
eats: true
};
let rabbit = Object.create(animal, {jumps: {value: true}})
console.log(rabbit.eats) // true
Summary
In JavaScript, we have the ability to use properties defined in one object to be used by different objects, which is known as Prototypal Inheritance.
JavaScript looks for inherited properties in the prototype of the object, but also in the prototype of the prototype, and so on in the chain of prototypes.
This is one of the classic ways of using OOPS in javascript and it’s very useful when used effectively.
Have any questions about prototypal inheritance? Let’s connect in a comment box!