Inheritance in JavaScript

If you have read first part of the series, Defining Classes in JavaScript, you are probably comfortable with the basic constructs of object orientation in JavaScript. The next important feature of object-oriented programming is the inheritance. Inheritance allows to create new classes which reuse, extend and modify the logic defined in other classes. It could give you lots of control and flexibility over your code.

As discussed in the previous post, function has prototype property and when this function is invoked using new keyword, it creates an object which contains all methods of the prototype. We will be leveraging this feature of JavaScript to achieve inheritance.

Following is the reusable function which encapsulates inheritance mechanism. Its normal, if it looks bit cryptic to you at first. We will break it in to four part to work through it.

var extend = function (sub, base) {
    for (var property in base) {
        if (base.hasOwnProperty(property)) {
            sub[property] = base[property];
        }
    }

    var Proxy = function () {};
    Proxy.prototype = base.prototype;
    sub.prototype = new Proxy();
    sub.prototype.constructor = sub;
    sub.base = base.prototype;
};

{% img /images/inheritance/extend.png %}

This function extend takes two arguments, first argument sub is the class which is inheriting and base is the class being inherited. Following section explains each part of this function

(A) Copy Base Class Properties

for(var property in base) lets us iterate through properties of the base class. These properties/methods could be object’s own or inherited from its base class(i.e. Object). We would be interested in replicating base class’s own properties only, so the if statement on the next line checks whether the property is base class’s own, if so simply assign it to the sub class through square bracket notation(i.e. similar to indexer in C#). This would make any properties or methods directly bound to the base class available in the sub class.

(B) Assign the Prototype

Now, we would like to get all the members declared as a part of prototype. Prototype is like a regular object, so we should be able to assign it directly like sub.prototype = base.prototype, however there is a catch here. As the prototype would be assigned as a reference, any further changes to the prototype done by the sub class would be reflected in the base class as well. To avoid this side effect, we would declare an empty function called ‘Proxy’, assign sub class as its prototype, create an instance of ‘Proxy’ and assign it as prototype of the sub class. This would severe the connection between the prototype of the base class and sub class. Here, you could see there is a very thin line between instance and the class in JavaScript.

(C ) Restore the Constructor

When we assigned the prototype of the base class to the sub class, it also got the constructor of the base class, restore it simply by assigning the sub as the constructor sub.prototype.constructor = sub.

(D) Add Reference to the Base Class

Assign prototype of the base class to a variable named base(to simulate the way C# exposes the base class), so it could be easily referred in the sub class. You will see it in a moment how it comes handy.

Let’s put it to use…

Now, lets extend the Car class defined in the previous post with the SportsCar class.

var Car, SportsCar;
//This is the Car class defined in the previous post, jump to line #35
Car = (function () {
    function Car(make, model) {
        this.make =  make;
        this.model =  model;

        var checkOilLife = function () {
            return 80; //just hard code to 80%
        };

        this.isServiceRequired = function () {
            return checkOilLife() < 20; //service required if oil life is below 20%
        };
    }

    Car.prototype.start = function () {
        console.log(' Started....' + this.model);
    };

    Car.prototype.stop = function () {
        console.log(' Stopped....' + this.model);
    };

    Car.wheelCount = 4;

    Car.isValidVIN = function (vin) {
        return vin !== null && vin.length === 17;
    };

    return Car;
}());

//This is were interesting things start...
SportsCar = (function () {
    extend(SportsCar, Car);
    function SportsCar() {
        return SportsCar.base.constructor.apply(this, arguments);
    };

    SportsCar.prototype.bounce = function () {
        console.log("Bouncing...." + this.model);
    };
    return SportsCar;
}());

First part simply defines the Car class, interesting things start at line #35 you could see how are we calling the extend method defined earlier by passing the SportsCar as sub class and Car as base class. Look at line number #38, where we are calling the constructor of the base class using the variable called base we sneaked in at the end of extend method. Further below you could see how we are introducing the method bounce, a method specific to the sub class.

It might take some time before all this feels natural, using it and seeing it in action would really make it easier. I would really like to hear your thoughts.