JavaScript Classes, Inheritance, and prototype chaining (ES5 and ES6 way)

August 30, 2019

With the release of ES6, we get the concept of classes in JavaScript. Classes allow us understanding and implementing the Object-Oriented Programming easily.

A JavaScript class (ES6)

One can relate a class in JavaScript to a class in an Object-Oriented Programming language. A class might look something like

As a programmer, we simply create instances of the class as
var user = new User('Kunal');

The class object gets logged as in the image above. See how an instance created for a class is represented internally with prototypes and the object’s key-value pairs.

Classes in ES5

The user instance we’ve just seen is represented by the prototypes and object’s key-value pairs which is the ES5 syntax. So we can clearly say that classes are just syntactical sugar over ES5 code.
Consider the scenario if you had to write the same code in ES5, without any syntactical sugar. We can use an object creation pattern here.
Don’t know about Object creation patterns?
Read more about them in my another article.
The code we have written above can be written in ES5 using the following constructor function.

As you can see, we get a similar output in the console as we get when creating an instance from class.

__proto__ inside __proto__

Did you notice that we are having a __proto__ inside the __proto__?
That’s Prototype Chaining.
In JavaScript, every object has a prototype and we also know that the prototype of an object which is also an object, thus creating nesting of prototypes.
So, JavaScript uses a similar concept for creating an inheritance by chaining multiple instances to prototypes and creating nested prototypes.
For example, the object shown in the above image is the User object. We can assign the User.prototype.prototype to be an instance of Person class. Thus creating an inheritance by chaining of the prototypes.
I will explain this in detail with the help of an example later in this article.

Objects created with classes (ES6) vs Objects created with constructor functions (ES5)

Although they seem to be same, upon expanding the inner __proto__, we get to see the difference among the two.
Upon expanding the __proto__ for the instance created with class syntax. We get nothing in the inner __proto__ object.

On the other hand, expanding the inner __proto__ for the instance created with constructor function gives the result as

This means the instance created by ES5 constructor function is inheriting from the JavaScript’s Object while the instance created with class syntax is not inheriting any of the properties from the JavaScript’s Object class.
With classes, we get no inheritance by default and we get a pure object assigned to the inner __proto__ property of the User object’s prototype.
We can also do that by explicitly modifying the inner __proto__ property.

Object.create(null) creates a pure object for us.


Implementing a simple inheritance in ES6 would look like the example below.
This will log the user as

On the outer prototype, we get the functions of User (printUser function) and on the inner prototype, we get the functions of Person (printPerson function).
We get the inheritance in action using the prototype chaining, but with a syntactical sugar.
While classes are just syntactical sugar over ES5. We must know how actually inheritance is implemented in ES5.
The above inheritance example using classes can be represented in ES5 using the following syntax

In the above code, we majorly need to understand two things:
  1. The __extends function
The __extends function takes two objects, the parent object, and the child object and set the prototype for the child.prototype to the instance of the parent object. calls the Person function with custom this context. Calling the Person function with custom this context includes the properties for Person object in the User object.
Now if we try to create the instance of the User class, we will get
var user = new User();

We get the same object as we received while creating an instance of the child class.
For the instance created, there are properties of both, User and Person. So the following two statements will return true.
console.log(user instanceof User);   // true
console.log(user instanceof Person); // true

You Might Also Like