JavaScript OOP : Inheritance

This post is part of a series of posts on JavaScript object-oriented programming. Link to the series are as follows:

This series is as follows:

  1. Pillars of Objected-Oriented Programming
  2. JavaScript Objects, prototype, constructor, & Object constructor
  3. Object Creation in JavaScript
  4. JavaScript OOP : Abstraction
  5. JavaScript OOP : Encapsulation
  6. JavaScript OOP : Inheritance
  7. JavaScript OOP : Polymorphism
  8. JavaScript OOP : Inheritance vs Composition

If you are still following this series, then you are doing really fine. Today we will continue this series with inheritance.

JavaScript doesn't have the concept of classes like in other programming languages like C# or Java. While ES6 introduces the concept of classes, it's just a wrapper around object. Everything in JavaScript is object We will further explain what that means when we talk about ES6 classes.

If you remember, we talked about prototype in our previous post Prototype holds the key to truly understand object-oriented programming in JavaScript. Prototype in JavaScript is simply, parent of another object. So when I use the word prototype, I am referring to the parent of an object e.g If object B inherits from object A, then B's prototype is A.

Prototypical Inheritance

Inheritance is the ability of an object to take on the property and method of another object. Meaning if object B inherits from object A, then object B should have all the properties and behaviours of object A.

To help solidify JavaScript OOP, we will use the analogy of shapes like Square, Circle, Triangle to illustrate this concept. Suppose we are tasked to implement a solution to store and keep tracks of different shapes, how would we go about designing our system conforming to OOP?

Our focus is on inheritance right now. Let's design out shape application. A shape object with a basic property or method that knows how to draw shapes.


    function Shape(){
    }

    Shape.prototype.draw = function(){
      console.log("This shape is drawn");
    };

Now we have a base object (Shape) which will serve as a prototype (or parent) to other types of shapes we will implement. Let's create a circle shape that inherits from our base Shape object.


    function Circle(radius){
      this.radius = radius;
    }

    //Circle inherits from Shape object
    Circle.prototype = Object.create(Shape.prototype);

    //Setting the constructor to Circle object
    //to allow for creation of new Circle Object
    Circle.prototype.constructor = Circle;

The parent object (Shape) has a property draw which is inherited by the the child object (Circle).

Now let's give each shape object color and names without repeating codes. We will further add other shapes such as triangle and rectangle. The list can go on and on for all possible shapes. However, we will stick to few shapes.


    function Shape(color, name){
        this.color = color;
        this.name = name;
    }

    Shape.prototype.draw = function(){
      console.log(`${this.name} with color ${this.color} is drawn!`);
    };


    //Circle Shape
    function Circle(radius, name, color){
        Shape.call(this, color, name); //Calling the base or parent class
        this.radius = radius;
      }

      //Circle inherit from Shape
      inherit(Shape, Circle);


    //Triangle Shape
    function Triangle(base, height, name, color){
        Shape.call(this, color, name);
        this.base = base;
        this.height = height;
      }

      //Triangle inherit from Shape
      inherit(Shape, Triangle);


      //Rectangle Shape
    function Rectangle(length, breath, name, color){
        Shape.call(this, color, name);
        this.length = length;
        this.breath = breath;
      }

      //Rectangle inherit from Shape
      inherit(Shape, Rectangle);


    function inherit(Parent, Child){
        Child.prototype = Object.create(Parent.prototype);
        Child.prototype.constructor = Child;
    }

Now we have different shapes implementing or inheriting from the Shape object. Let's have a quick look how the children object behave. I have encapsulated the two lines of code of changing the prototypes into a re-usable function inherit to make our code easy to read.


    let circle = new Circle(10, 'Circle', 'red'),
        triangle = new Triangle(5, 10, 'triangle', 'black'),
        rectangle = new Rectangle(10, 10, 'rectangle', 'blue');

In addition to their proprties, all the children objects now have access to the parent(prototype) object property.

This completes the basis of inheritance in object-oriented JavaScript.

Happy Coding...