Saturday, 10 May 2014

Classical inheritance in JavaScript


There is already a lot of good stuff about JavaScript's inheritance on the web. So WHY another post?

The reason being, this post will not only answer HOW to achieve inheritance but also WHY it is done so.

Let's start by answering them:
  • HOW is inheritance achieved in JavaScript? and then
  • WHY is it achieved so?
Before jumping to HOW, we must know the ways of creating private and public members in a Class (which is actually a function in JavaScript.).  Referring to Crockford's article here this is how we create private and public members.

Private Members:

Parameters to a function and variables declared with vars become private.
function MyClass (privateMember1, privateMember2) {
    var privateMember3;
}

Public Members:

Public members can be added in two ways:
  • Method 1: In the constructor
function MyClass (privateMember1, privateMember2) {
    var privateMember3;
    this.publicMember1 = 'I am public';
}
  • Method 2: In the prototype
MyClass.prototype.publicMember2 = 'I am public, too';

Fine. Now let's answer HOW.
When you inherit from a Class you actually inherit its public members. Now, point to be noted is the one we have seen above that public members can be added in 2 ways.

Let's take an example.
// Shape: Superclass
function Shape(type) {
    // Adding public member using method 1.
    this.type = type;
}

// Adding public member using method 2.
Shape.prototype.fillColor = function (color) {
    console.log("Shape filled with %s color.", color);
};

// Rectangle: Subclass
function Rectangle(length, breadth) {
    this.length = length;
    this.breadth = breadth;

    // Call Superclass' constructor which will
    // inherit public members added using method 1.
    Shape.call(this, '2D');
}

// Set prototype to inherit public members added
// using method 2.
Rectangle.prototype = Object.create(Shape.prototype);

//Set constructor to SubClass
Rectangle.prototype.constructor = Rectangle;

// Add Subclass specific method.
Rectangle.prototype.getArea = function () {
    return this.length * this.breadth;
};

var rectangle = new Rectangle(8, 5);
console.log(rectangle instanceof Rectangle);
// Output: true

console.log(rectangle instanceof Shape);
// Output: true

console.log('Rectangle shape type is ', rectangle.type);
// Output: Rectangle shape type is  2D

rectangle.fillColor('Red');
// Output: Shape filled with Red color.

console.log('Area of rect is ', rectangle.getArea());
// Output: Area of rect is  40


Each part of the code has comments to explain what it does.

You must have already got to know the WHY part while reading the comments in the code. Let's repeat it for the sake of completion.

We did
Shape.call(this, '2D');
to  inherit public members added using method 1 and
Rectangle.prototype = Object.create(Shape.prototype);
to inherit public members added using method 2.

Much obvious but worth understanding and once you understand you don't have to remember it.