Inheritance in JavaScript - Part 2 of 3

This is the second article in a series about prototypal inheritance in JavaScript. Have a look at the first article about Inheritance in JavaScript.

The prototype chain is the way inheritance in JavaScript is achieved. There are three common ways to create a prototype chain:

  • functional
  • constructor functions (this article)
  • class-syntax constructors

This article will cover the constructor functions approach on creating prototype chains.

Prototypal Inheritance (Constructor Functions)

The creation of an object with a specific prototype object can be achieved by calling a function with the new keyword. This is a very common pattern in older code bases.

All functions have a prototype property. To create a prototype with a constructor function, the properties have to be defined on the function's object and then the function has to be called with the new keyword.

For the example code, we will use the animal and dog taxonomy, where animal is a prototype of dog.

function Animal(name) {
  this.name = name;
}

Animal.prototype.eat = function() {
  console.log(this.name + ' eats');
};

function Dog(name) {
  Animal.call(this, name);
}

// this is a helper function and it could look different in older code bases
function inherit(proto) {
  function ChainLink() {}
  ChainLink.prototype = proto;
  return new ChainLink();
}

Dog.prototype = inherit(Animal.prototype);

Dog.prototype.bark = function() {
  console.log(this.name + ' barks');
};

const henry = new Dog('Henry');

henry.bark();
henry.eat();

The code above results in the exact prototype chain as in the functional approach.

console.log(Object.getPrototypeOf(henry) === Dog.prototype); //Will be true
console.log(
  Object.getPrototypeOf(Dog.prototype) === Animal.prototype,
); //Will be true

It's a convention to write the functions called with new (Animal and Dog) in PascalCase.

The eat method was added to Animal.prototype without ever instantiating an object and assigning it to Animal.prototype. The reason for this is that every function has a pre-existing prototype object. The Dog.prototype was explicitly assigned and overwrites the previous Dog.prototype object.

The prototype chain looks like this:

  • the prototype of henry is Dog.prototype
  • the prototype of Dog.prototype is Animal.prototype
  • the prototype of Animal.prototype is Object.prototype.

With ECMAScript 5+ instead of the inherit function, the Object.create method could be used.

function Dog(name) {
  Animal.call(this, name);
}

Dog.prototype = Object.create(Animal.prototype);

Dog.prototype.bark = function() {
  console.log(this.name + 'barks');
};

In Node.js there is a utility function for this util.inherits.

const util = require('util');

function Dog(name) {
  Animal.call(this, name);
}
Dog.prototype.bark = function() {
  console.log(this.name + ' barks');
};
util.inherits(Dog.prototype, Animal.prototype);

TL;DR

  • Inheritance in JavaScript is achieved with a chain of prototypes
  • There are three common ways to create a prototype chain (functional, constructor functions, class-syntax constructors)
  • The constructor approach is to define properties on a function's prototype object and then call it with new.
  • util.inherits is a utility function in Node.js to set and overwrite prototypes of objects.

Thanks for reading and if you have any questions , use the comment function or send me a message @mariokandut.

If you want to know more about Javascript , have a look at these Javascript Tutorials.

References (and Big thanks)

13