Nested inheritance in Javascript

Most examples of javascript inheritance only go one level deep (for example, Student inherits (→) from Person). That’s all well and good, but what if you have a long chain for things you want to inherit from?

Say we have A → B → C → D → E, and each has its own methods and attributes. How can they inherit from each other cleanly?

Here is the initial solution:

So, what’s special about the above. Not much… except the the only gotcha is the ordering of:

//you need to make sure you don't override your functions
//Good:
X.prototype = new Y();
X.prototype.foo = function(){ .... };

//Bad (trashes foo!)
X.prototype.foo = function(){ .... };
X.prototype = new Y();

Adding methods and properties

Once we have a chain, we naturally want to make objects created from that chain do something useful. The above A, B, C, etc. is a little academic, so lets now use a more “real world” example.

Lets say we have the following inheritance chain of vehicle types:

Vehicle → LandVehicle → Car → SportsCar → RacingCar

We assume that all Vehicles have a “registration” property that is unique for each vehicle we create:

The problem when we run the above is that the registration is not unique! When we are constructing the new RacingCar(), we are using the same prototype for all instances (in fact for any kind of Vehicle).

To solve this problem, we need to make sure that for “this” instance we are given a unique “registration”. To do that, we need to “call()” the function from which we are inheriting from using “this“, like so:

function RacingCar(){Vehicle.call(this)}

So, that makes sure that “this” (whatever that is associated with) gets the right “registration” number (i.e., a random number):

Ok, so far so good… but if we start adding methods and unique properties on each level, we are going to have the same problem. So what we can do is just cascade “this” through the inheritance chain:

function LandVehicle(){Vehicle.call(this)}
function Car(){LandVehicle.call(this)}
function SportsCar(){Car.call(this)}
function RacingCar(){RacingCar.call(this)}

Now we can start individualising each object to our needs. The following shows a complete set of custom objects that inherit from each other. It also shows “static” functions and property being declared (e.g., the make of a Car and getting a randomMake() for either a bike or car):

So there you have it. Classical inheritance JavaScript styles.

5 thoughts on “Nested inheritance in Javascript

  1. Great article!
    @WebReflection also has some good insights about inheritance in JavaScript: http://webreflection.blogspot.com/search/label/inheritance

    Another way to construct the prototype chain is by using Object.create, this way you don’t need to worry with constructor parameters. LandVehicle, for instance, receives numberOfTires as a parameter but we don’t care about that when creating the Car prototype chain, an alternative is to:

    Car.prototype = Object.create(LandVehicle.prototype, {
    horn: {
    value: function() {
    console.log(“Honk!”);
    }
    },
    drive: {
    value: function() {
    console.log(“Vroom!”);
    }
    },
    constructor: {
    value: Car
    }
    });

    http://jsfiddle.net/YVdxp/

  2. Pingback: Bruce Lawson’s personal site  : Reading List

  3. A little overide in Function.prototype and the use of override as a “keyword”, allows for calling of the super function:

    Function.prototype.override = function(func)
    {
    var superFunction = this;
    return function()
    {
    this.superFunction = superFunction;
    return func.apply(this,arguments);
    };
    }

    function A()
    {
    this.foo = function()
    {
    document.write(“A”);
    }
    };

    function B()
    {
    A.call(this);
    this.foo = this.foo.override(function()
    {
    this.superFunction();
    document.write(‘B’);
    });
    };

    function C()
    {
    B.call(this);
    this.foo = this.foo.override(function()
    {
    this.superFunction();
    document.write(‘C’);
    });
    };

    var o = new C();

    o.foo();

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>