How Prototypal Inheritance works in JavaScript

How Prototypal Inheritance works in JavaScript

And how to convert it to class based inheritance

Before starting with prototypal inheritance let’s first understand what a prototype is.

All the objects in JavaScript like Array, Boolean, Date etc all inherit properties and methods from their prototype.

Object is the at top of the Prototype chain means all the other objects inherit their properties and methods from Object.prototype.

Suppose we have Person object constructor:

function Person(name, age) {
 this.name = name;
 this.age = age;
}

Then we create objects of Person as follows:

const person1 = new Person("David", 30);
const person2 = new Person("John", 35);

console.log(person1); // {name: "David", age: 30}
console.log(person2); // {name: "John", age: 35}

If we want to add another property to the Person object we can add that to an individual object like this:

person1.gender = 'Male';

but this will only add this property to person1 object.

console.log(person1.gender); // Male
console.log(person2.gender); // undefined

To add the property to the Person object itself we have to add it to its prototype before creating objects so it will be available to all of its objects.

Person.prototype.gender = 'Male';

const person1 = new Person("David", 30);
const person2 = new Person("John", 35);

console.log(person1.gender); // Male
console.log(person2.gender); // Male

We can also add methods to the Person prototype like this:

Person.prototype.display = function() {
 console.log(this.name, this.age);
};

const person1 = new Person("David", 30);
const person2 = new Person("John", 35);

person1.display(); // David 30
person2.display(); // John 35

So to add any property or method to an object, we need to add it to its prototype.

If we compare the person1 and person2 display methods we will see that it returns true

console.log(person1.display === person2.display) // true

It returns true because in memory there is only a single copy of the display function because we added the method to its prototype so it's shared by all objects.

Let's see what happens when we add it directly inside the Person constructor

function Person(name, age) {
 this.name = name;
 this.age = age;
 this.display = function() {
  console.log(this.name, this.age);
 };
}

const person1 = new Person("David", 30);
const person2 = new Person("John", 35);

person1.display(); // David 30
person2.display() // John 35

Now, let's compare the display methods:

console.log(person1.display === person2.display) // false

Now it displays false because as we have added the method directly to the constructor function, each object created from Person will have its own copy of function so there are two copies of display function in memory here and as we create more objects, the number of copies of display function inside memory will also increase.

So it's a bad practice and it's not recommended to create methods directly inside the constructor function instead we should add them to the prototype.

Now, we have some basic knowledge of prototypes, let's understand prototypal inheritance now.

Prototypal Inheritance

Let's start with the same Person example above.

function Person(name, age) {
 this.name = name;
 this.age = age;
}

Person.prototype.display = function() {
 console.log(this.name, this.age);
};

Now, let's create an Employee constructor function that will inherit the properties and methods of the Person.

function Employee(name, age, salary) {
 Person.call(this, name, age);
 this.salary = salary;
}

const emp = new Employee('Mike', 20, 4000);

Here, we are using Person.call function to call the Person’s constructor and pass the name and age to it.

Now, let’s check what emp contains:

console.log(emp); // {name: "Mike", age: 20, salary: 4000}

As you can see, it contains all the properties of Person plus its own properties.

Now, let's call the display method using the emp object.

emp.display(); //  Error: emp.display is not a function

Why do we get the error?

This is because we only mentioned inheriting properties of Person using Person.call(this, name, age)

To inherit methods also, we need to link the prototype and then create an object.

Employee.prototype = Object.create(Person.prototype);

const emp = new Employee('Mike', 20, 4000);
emp.display(); // Mike 20

Now, let’s check the type of Employee which we can check using constructor property

console.log(emp.constructor) // Person
console.log(Employee.prototype.constructor) // Person

It prints Person which is wrong because we know that, it should be Employee. The constructor property should always return the correct type.

Suppose, we have an array:

const numbers = [1, 2, 3, 4];

console.log(typeof numbers); // "object"

We get an object because every array in JavaScript is an object so to get its correct type we can use constructor property that returns the correct type.

console.log(numbers.constructor) // Array
console.log(numbers.constructor === Array) // true

So to fix the issue with Employee constructor we need to change its constructor type

Employee.prototype.constructor = Employee;

console.log(emp.constructor) // Employee
console.log(Employee.prototype.constructor) // Employee

Now, we get the correct result. The complete prototypal inheritance will look like this

As you can see, even for the simple prototypal inheritance we have to add a lot of extra code.

Therefore ES6 has added class syntax which allows us to implement the same in an easy way.

As you can see, the class-based syntax is short and easy to understand when compared with prototypal inheritance.

Note: The class at the end uses the prototypal inheritance itself. It’s just that, we don’t need to worry about it

Thanks for reading!

Starting with ES6, there are many useful additions to JavaScript like:

  • ES6 Destructuring
  • Import and Export Syntax
  • Arrow functions
  • Promises
  • Async/await
  • Optional chaining operator and a lot more.

You can learn everything about all the ES6+ features in detail in my Mastering Modern JavaScript book.

Check out free preview contents of the book here.

Also, you can check out my free Introduction to React Router course to learn React Router from scratch.

Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.

Did you find this article valuable?

Support Yogesh Chavan by becoming a sponsor. Any amount is appreciated!