Before you go, check out these stories!

0
Hackernoon logoYou don’t simply inherit in JS by@rohanbagchi

You don’t simply inherit in JS

Author profile picture

@rohanbagchiRohan Bagchi

“Colorful lines of code on a MacBook screen” by Caspar Rubin on Unsplash
Disclaimer: this is a slightly opinionated post. Feel free to disagree in comments :)

Overtime, this has become a standard question in interviews for a frontend/full stack role:

What is the difference between classical & prototypal inheritance in JS?

or it’s alter ego:

How do you do classical inheritance and how do you do prototypal inheritance in JS?

To answer the first, there is no difference. Conversely, classical & prototypal inheritance is the same thing. Or rather, we implement classical inheritance using prototype chaining or inheritance.

Second and the most important, inheritance inherently means copying of properties & behaviour. Here, by virtue of prototype chaining, it is merely delegation. Will explain further below.

Classical Inheritance is where properties and behaviour are inherited from some map / blueprint.

Think of it like constructor functions mapping to another via prototype chaining.

Mind the following code block:

At this point, when we create a new object from Bar it will get the properties attached to this of Foo like this:

const bar_object = new Bar();
console.log(bar_object.name); // prints 'Hello'
console.log(bar_object.age); // prints '31'

However, when we attach a new behaviour to Foo’s prototype, this is not available to bar_object . As in,

Foo.prototype.sayName = function() {
console.log('My name is '+this.name);
}

Now if we do this:

bar_object.sayName(); // it throws an error

But ideally this should be available because we are attempting to perform inheritance and anything on the parent should be available to child. In this spirit, this is what we need to do make it work:

Mind Line 10. We are reassigning the prototype property on Bar function to another object.

According to MDN, this is what Object.create does.

Essentially, it is creating a new object with it’s prototype set to the passed in argument, Foo.prototype .

What this means is, going forward, all objects created out of Bar using it as a constructor function will have access to the behaviour / methods we add to Foo.prototype .

If we think of the Foo & Bar as classes with properties, they are basically blueprints of how objects created out of them should look like, similar to how we have classes and their instances in Java / Python.

Here, JS is made to behave like Java by coercing a prototype relationship.

What we did above is Classical Inheritance using prototype chaining, and this is also called Prototypal Inheritance as people think it is ok to add a qualifier like Classical or Prototypal to an age old term Inheritance and think it is ok.

When we do this bar_object.sayName() we are essentially invoking the method defined on Foo.prototype and not our original constructor function Bar's copied/inherited method.

However, the magic is not over yet. You see, the prototype also has a constructor property that maps to the constructor function. It’s use case can be in objects created out of a function to know the constructor that created it.

However, we directly updated the prototype property of the Bar and as such, it’s constructor property will point to Foo .

While we wouldn’t normally rely on the constructor property, it is still dirty code. So to clean up our act, we have to also modify the constructor property in Bar.prototype . This is the complete code where inheritance happens from Foo to Bar .

There is however another school of thought where in it is said that prototypal inheritance is basically an inheritance involving prototypes or objects like this:

const foo = {
name: 'John'
};
const bar = {
age: 21
};
const foobar = {
...foo,
...bar,
hotel: 'tango'
};

This has been mentioned and explained beautifully here:

To sum it up, next time some one asks you the classical / prototypal inheritance family of questions, tell them this:

You implement classical inheritance using prototypal inheritance / chaining / delegation . One cannot exist without the other.

Read up:

Thanks for reading.

Hit *clap* if you think this was worth your while :)

Find me on linkedin or revert back to me on comments.

I write about tech, mostly JavaScript: React, Redux, react app performance stories and frontend engineering.

Tags

The Noonification banner

Subscribe to get your daily round-up of top tech stories!