JavaScript Inheritance Patterns

In this post, I am going to introduce to you 3 different ways of how you can implement inheritance in JavaScript. You will see inheritance implemented in languages such as Java by allowing a class to inherit state and behavior from a superclass, where each superclass can have many subclasses.

This means that in Java an object is an instance of a class, which can inherit other classes. Now in JavaScript, being prototypal by nature, an object can inherit from an object.

For the rest of this post, I will introduce the Pseudoclassical, Functional and Prototypal inheritance patterns in JavaScript.

Pseudoclassical pattern

The Pseudoclassical pattern tries to replicate inheritance in a way that is familiar to those who come from a Java or C like background. By using Pseudoclassical inheritance, we attempt to recreate classic programming language’s behavior by using class wide inheritance and where objects are instances of those classes.

A pattern which uses a constructor function and the new operator, combined with a prototype added to the constructor is said to be Pseudoclassical.

In JavaScript, one way to do this inheritance is:

  1. Invoke a constructor function.
  2. Point a child’s prototype to the parent’s prototype for inheritance to occur.
/**
 * Point a child's prototype to a parent's prototype
 **/
var extendObj = function(childObj, parentObj) {
    childObj.prototype = parentObj.prototype;
};

// base human object
var Human = function() {};
// inhertiable attributes / methods
Human.prototype = {
    name: '',
    gender: '',
    planetOfBirth: 'Earth',
    sayGender: function () {
        alert(this.name + ' says my gender is ' + this.gender);
    },
    sayPlanet: function () {
        alert(this.name + ' was born on ' + this.planetOfBirth);
    }
};

// male
var Male = function (name) {
    this.gender = 'Male';
    this.name = 'David';
};
// inherits human
extendObj(Male, Human);

// female
var Female = function (name) {
    this.name = name;
    this.gender = 'Female';
};
// inherits human
extendObj(Female, Human);

// new instances
var david = new Male('David');
var jane = new Female('Jane');

david.sayGender(); // David says my gender is Male
jane.sayGender(); // Jane says my gender is Female

Male.prototype.planetOfBirth = 'Mars';
david.sayPlanet(); // David was born on Mars
jane.sayPlanet(); // Jane was born on Mars

As expected, we have achieved inheritance in a Pseudoclassical manner, however, this solution has a problem. If you look at the last line, you will see the alert says Jane was born on Mars, but what we really want it to say is Jane was born on Earth. The reason for this is the Male prototype was changed to “Mars”.

Given the direct link between the Male and Human prototype, if Human has many children inheriting from it, any change on a child’s prototype properties will affect Human, and thus all children inheriting from Human. Changing a child’s prototype should not affect other children inheriting from the same parent. The reason for this is because JavaScript passes objects by reference, not by value, meaning all children of Human inherit changes occurred on other children’s prototypes.

childObj.prototype = parentObj.prototype does give us inheritance. However, if you want to fix the issue above, you need to replace the extendObj function to take the child’s prototype and link it to a temporary object, whose prototype is the parent object’s prototype. In this way, by creating a temporary “middle” object, you allow the temporary object to be empty and inherit its properties from Human.

By doing this, you have solved the pass by reference issue with a new instance of an empty object, which still inherits from the parent, but is not affected by other children.

To understand this clearly, the image below shows the flow of the extendObj function.

classical inheritance

Now, if you ran the same code again, but with the changes in extendObj below, you would see “Jane was born on Earth” was alerted.

/**
 * Create a new constructor function, whose prototype is the parent object's prototype.
 * Set the child's prototype to the newly created constructor function.
 **/
var extendObj = function(childObj, parentObj) {
    var tmpObj = function () {}
    tmpObj.prototype = parentObj.prototype;
    childObj.prototype = new tmpObj();
    childObj.prototype.constructor = childObj;
};

// base human object
var Human = function () {};
// inhertiable attributes / methods
Human.prototype = {
    name: '',
    gender: '',
    planetOfBirth: 'Earth',
    sayGender: function () {
        alert(this.name + ' says my gender is ' + this.gender);
    },
    sayPlanet: function () {
        alert(this.name + ' was born on ' + this.planetOfBirth);
    }
};

// male
var Male = function (name) {
    this.gender = 'Male';
    this.name = 'David';
};
// inherits human
extendObj(Male, Human);

// female
var Female = function (name) {
    this.name = name;
    this.gender = 'Female';
};
// inherits human
extendObj(Female, Human);

// new instances
var david = new Male('David');
var jane = new Female('Jane');

david.sayGender(); // David says my gender is Male
jane.sayGender(); // Jane says my gender is Female

Male.prototype.planetOfBirth = 'Mars';
david.sayPlanet(); // David was born on Mars
jane.sayPlanet(); // Jane was born on Earth

Functional pattern

Another pattern you can use to achieve inheritance in JavaScript is by Douglas Crockford, called Functional inheritance. This pattern allows one object to inherit from another, take the result and augment it at the child level to achieve inheritance. What this really means, is you create an object as your parent, pass the child object to the parent to inherit / apply its properties, and return the resulting object back to the child, who can then augment its own properties to the object returned from the parent.

Below is the same example used above to explain Pseudoclassical inheritance, but written in a functional nature.

var human = function(name) {
    var that = {};

    that.name = name || '';
    that.gender = '';
    that.planetOfBirth = 'Earth';
    that.sayGender = function () {
        alert(that.name + ' says my gender is ' + that.gender);
    };
    that.sayPlanet = function () {
        alert(that.name + ' was born on ' + that.planetOfBirth);
    };

    return that;
}

var male = function (name) {
    var that = human(name);
    that.gender = 'Male';
    return that;
}

var female = function (name) {
    var that = human(name);
    that.gender = 'Female';
    return that;
}

var david = male('David');
var jane = female('Jane');

david.sayGender(); // David says my gender is Male
jane.sayGender(); // Jane says my gender is Female

david.planetOfBirth = 'Mars';
david.sayPlanet(); // David was born on Mars
jane.sayPlanet(); // Jane was born on Earth

As you can see by using this pattern, there is no need to use the prototype chain, constructors or the “new” keyword. Functional inheritance achieves this by passing a unique object around every time an instance of the function is called.

This however, has a downside for performance because each object is unique, meaning each function call creates a new object, so the JavaScript interpreter has to assign new memory to the function in order to recompile everything inside of it as unique again.

There are also benefits to this approach, as the closures of each function allow for good use of public and private methods / attributes. Let’s take this code for example, which shows a parent class of vehicle and children classes of motorbike and boat.

var vehicle = function(attrs) {
    var _privateObj = {
        hasEngine: true
    },
    that = {};

    that.name = attrs.name || null;
    that.engineSize = attrs.engineSize || null;
    that.hasEngine = function () {
        alert('This ' + that.name + ' has an engine: ' + _privateObj.hasEngine);
    };

    return that;
}

var motorbike = function () {

    // private
    var _privateObj = {
        numWheels: 2
    },

    // inherit
    that = vehicle({
        name: 'Motorbike',
        engineSize: 'Small'
    });

    // public
    that.totalNumWheels = function () {
        alert('This Motobike has ' + _privateObj.numWheels + ' wheels');
    };

    that.increaseWheels = function () {
        _privateObj.numWheels++;
    };

    return that;

};

var boat = function () {

    // inherit
    that = vehicle({
        name: 'Boat',
        engineSize: 'Large'
    });

    return that;

};

myBoat = boat();
myBoat.hasEngine(); // This Boat has an engine: true
alert(myBoat.engineSize); // Large

myMotorbike = motorbike();
myMotorbike.hasEngine(); // This Motorbike has an engine: true
myMotorbike.increaseWheels();
myMotorbike.totalNumWheels(); // This Motorbike has 3 wheels
alert(myMotorbike.engineSize); // Small

myMotorbike2 = motorbike();
myMotorbike2.totalNumWheels(); // This Motorbike has 2 wheels

myMotorbike._privateObj.numWheels = 0; // undefined
myBoat.totalNumWheels(); // undefined

You can see that it is fairly easy to provide encapsulation. The _privateObj can not be modified from outside of the object, unless exposed by a public method like increaseWheels(). Similarly, private values can also only be read when exposed by a public method, such as motorbike’s totalNumWheels() function.

Prototypal pattern

You can also implement inheritance in JavaScript using a pure prototypal approach which is more suited to the language.
As of ECMAScript 5, it is possible to create an inherited object by simply doing the following:

var male = Object.create(human);

However, support is not so good for older browsers, thankfully you can augment the Object with a create method should it not exist already, which will have the same behavior as that of ECMAScript 5.

(function () {
    'use strict';

    /***************************************************************
     * Helper functions for older browsers
     ***************************************************************/
    if (!Object.hasOwnProperty('create')) {
        Object.create = function (parentObj) {
            function tmpObj() {}
            tmpObj.prototype = parentObj;
            return new tmpObj();
        };
    }
    if (!Object.hasOwnProperty('defineProperties')) {
        Object.defineProperties = function (obj, props) {
            for (var prop in props) {
                Object.defineProperty(obj, prop, props[prop]);
            }
        };
    }
    /*************************************************************/

    var human = {
        name: '',
        gender: '',
        planetOfBirth: 'Earth',
        sayGender: function () {
            alert(this.name + ' says my gender is ' + this.gender);
        },
        sayPlanet: function () {
            alert(this.name + ' was born on ' + this.planetOfBirth);
        }
    };

    var male = Object.create(human, {
        gender: {value: 'Male'}
    });

    var female = Object.create(human, {
        gender: {value: 'Female'}
    });

    var david = Object.create(male, {
        name: {value: 'David'},
        planetOfBirth: {value: 'Mars'}
    });

    var jane = Object.create(female, {
        name: {value: 'Jane'}
    });

    david.sayGender(); // David says my gender is Male
    david.sayPlanet(); // David was born on Mars

    jane.sayGender(); // Jane says my gender is Female
    jane.sayPlanet(); // Jane was born on Earth
})();

Summary

So today we have covered 3 different ways that you can implement inheritance in JavaScript. Most people are aware of prototypes, but as we have seen today, the Pseudoclassical and Functional patterns are just as valid.

Which pattern you should use varies depending on your project, there is no real “1 fits all” solution, so you are best to choose 1 you feel is the most suitable.

Comments

  1. Instead of doing:

    var tmpObj = function () {}
    tmpObj.prototype = parentObj.prototype;
    childObj.prototype = new tmpObj();
    childObj.prototype.constructor = childObj;

    Can't you just do:

    childObj.prototype = new parentObj();

    It seemed to work for me.

    Reply
    • @Jacob

      By doing:

      childObj.prototype = new parentObj();

      You of course still achieve inheritance as you are creating a new parentObj which by nature inherits from parentObj.prototype.

      However, there are 2 reasons I would not recommend using this:

      1. If the parentObj constructor requires arguments, things often get messy and can have side-effects.
      2. From a theoretical point of view, we actually do not want to create a whole new parentObj, we simply want to inherit from it.

      Reply
  2. Pingback: JavaScript Inheritance Patterns « thoughts…

  3. Hi. I’m from Brazil, so forgive me for some eventual English mistakes.

    First of all, congratulations for you website.

    hey, about this patterns, I have chosen one of them to use in most of my codes: Functional pattern.

    I chose this because I was facing many troubles with the ‘this’ inside my codes. They weren’t ‘big’ problems, but were bad enough for me to chose functional pattern.

    I agree with you when you say that we don’t have to take a pattern as our “all solutions”, but functional looks ‘better’ for me – funnier to write, at least =] .

    But I haven’t seen many posts about this pattern over the web. Actually, your post is the first (maybe second) I’ve seen. Why do you think this happens? Why anyone have knowledge about this pattern?

    I’m not a big fan of prototype so I try to avoid it. Do you think the performance have a big ‘decrease’ because the use of functional?

    I think that the maintainability of a code using functional pattern is higher than using prototype and this maintainability compensates the performance, don’t you think?

    Reply
  4. Thanks for an interesting write up. It’s great to see these patterns side by side so the similarities and differences can be fully appreciated.

    There are two points I would love to read your opinion about which follow naturally from this discussion:
    1. overloading/overriding object methods by its children, with the possibility of calling some form so super method (or by name).
    2. adding mixins to the mix (pun intended) – how to do it in a way that mixed in methods/properties are inherited.

    If I understand correctly the different patterns you described will have differences in the constraints and challenges of trying to implement super calls or mixins.

    Reply
  5. For the example “Pseudoclassical pattern”, when you said

    “However, this solution has a problem. If you look at the last line, you will see the alert says “Jane was born on Mars”, it should say “Jane was born on Earth”. The reason for this is the Male prototype was changed to “Mars”.”

    Its because you did :

    Male.prototype.planetOfBirth = ‘Mars’;

    instead of :

    Male.planetOfBirth = ‘Mars’;

    the second line will create a inner property planetOfBirth for Male, Women will still keep Earth from its prototype.

    ————————————–

    for the second part :

    var extendObj = function(childObj, parentObj) {
    var tmpObj = function () {}
    tmpObj.prototype = parentObj.prototype;
    childObj.prototype = new tmpObj();
    childObj.prototype.constructor = childObj;
    };

    mmmm I dont like it, you create a new prototype object each time, meaning 1000 object mean 1000 prototype in memory.

    Reply
  6. Pingback: Learn | Pearltrees

  7. @David Shariff
    If classical inheritance is what you are trying to achieve, then I think Jacobs reply is valid. In C++ and Java you do create a new instance of the base-class for each sub-class instance . And you have to pass any required arguments to base-class constructors in the sub-class constructor.
    function Subclass( arg ) {
    this.protorype = new Baseclass( arg, “foo” );
    }

    Reply
  8. Pingback: Javascript Inheritance | Croteau's Blog

  9. I believe you forgot to use var in the second block of code under “Functional pattern”.

    that = {};

    should probably be

    var that = {};
    
    that = vehicle({
            name: 'Motorbike',
            engineSize: 'Small'
        });
    

    should probably be

    var that = vehicle({
            name: 'Motorbike',
            engineSize: 'Small'
        });
    

    etc.

    Otherwise you risk overriding any global variable named that.

    Still, nice summary of different inheritance patterns.

    Reply
    • @Lars

      The var was already declared, I used a comma after the _privateObj. Probably the spacing after the object didn’t make it clear:

      // private
      var _privateObj = {
          numWheels: 2
      }, < ---HERE
      
      // inherit
      that = vehicle({
          name: 'Motorbike',
          engineSize: 'Small'
      });
      
      Reply
  10. Pingback: JavaScript Inheritance Patterns by David Sharif...

  11. Pingback: JavaScript Inheritance Patterns by David Shariff | InhumanBlog

  12. Pingback: 5 Attempts At Type Safety In JavaScript | Nightlight

Leave a Reply

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


3 × nine =

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>