Let’s consider that square is a special type of rectangle, whose length and width are equal. Thus we can create blueprint of a square by extending the blueprint of a rectangle. I am using the term blueprint as JavaScript/ECMAScript version prior ES2015 did not have class functionality.

Pre ES5

Let’s create blueprint of a rectangle

function Rectangle(length, width) {
  this.length = length;
  this.width = width;
}

Rectangle.prototype.getArea = function() {
  return this.length * this.width;
}

Now, let’s create blueprint of a square by extending the above blueprint of a rectangle

function Square(length) {
  Rectangle.call(this, length, length);
}

Let’s create an instance of square

var square = new Square(3);
console.log('square.length: ', square.length); // square.length: 3
console.log('square.width: ', square.width); // square.width: 3

That’s good, the length and width of the square has been set without any explicit code. Rectangle.call(this, length, length); is behind the magic. Rectangle is being invoked with the context of current this; i.e. Square with same value for length as well as width.

Let’s print the area of the square

console.log('square.getArea(): ', square.getArea()); // Uncaught TypeError: square.getArea is not a function

Well, there is no getArea function associated with Square, but there is a getArea function associated with Rectangle. So, the inheritance did not establish properly.

JavaScript inheritance is established via the prototype chain and the square instance created above does not have any link to the Rectangle Please refer the below image. square.__proto__

We could establish the prototype chain between Square and Rectangle by assigning an instance of Rectangle to Square’s prototype.

Square.prototype = new Rectangle();

Please refer the below example:

See the Pen JavaScript Inheritance - Pre ES5 by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

What is the purpose of Square.prototype.constructor = Square;?

Every instances of Square will have a constructor of Square, not of Rectangle.

If we plan to create another instance of Square with respect to an existing instance of Square, we need the above line. For example, if we comment out the Square.prototype.constructor = Square; and try to create another instance of Square from an existing instance of Square; the toString method of the new instance will refer to the toString method of the Rectangle blueprint instead of the Square blueprint.

...
// Square.prototype.constructor = Square;
...

var anotherSquare = new square.constructor(4);
console.log('anotherSquare.toString(): ', anotherSquare.toString()); // anotherSquare.toString(): a rectangle
console.log('square.toString(): ', square.toString()); // square.toString(): a square

Please refer the below example:

See the Pen JavaScript Inheritance - Pre ES5 - w/o constructor by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

ES5

If you have got the hang of prototype and constructor in the pre ES5 example, comprehending the ES5 compliant example would be easy.

Instead of

Square.prototype = new Rectangle();
Square.prototype.constructor = Square;

we will use

Square.prototype = Object.create(Rectangle.prototype, {
    constructor: {
        value:Square,
        enumerable: true,
        writable: true,
        configurable: true
    }
});

We are utilizing ES5 Object.create functionality.

Please refer the below example:

See the Pen JavaScript Inheritance - ES5 by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

ES2015

ES2015 comes with class, extends, super, and makes inheritance achievable in lesser lines, similar to other object oriented languages.

class Rectangle {
  constructor(length, width) {
    ...
  }
}

class Square extends Rectangle {
  constructor(length) {
    super(length, length); // same as Rectangle.call(this, length, length)
  }
}

We no longer need to set the prototype and prototype.constructor explicitly.

Please refer the below example:

See the Pen JavaScript Inheritance - ES2015 by Sarbbottam Bandyopadhyay (@sarbbottam) on CodePen.

Further reading


If you have enjoyed reading this post you can follow me on twitter @sarbbottam and learn about any new posts. Opinions expressed are solely my own and do not express the views or opinions of my employer.