JavaScript Inheritance Advice

Posted on April 12, 2015 by Brian Jaress
Tags: code, advice

It’s hard to find comprehensive advice online about doing class-based inheritance in JavaScript because everyone just gives their preferred solution. Here’s a rundown of what to do and what to fall back on if that’s not possible:

Here’s a pattern that’s so lightweight it’s really just a convention, so easy you can use it every time you need a constructor, and so straightforward no one can claim it’s too fancy:

(function(){ //scope wrapper

    this.Book = function(words) {
        this.words = words;
    };
    var prot = this.Book.prototype;

    prot.read = function() {
        return this.words;
    };

    prot.getLength = function() {
        return this.words.length;
    };

}).call(this);

For any class that’s not a subclass, that’s it. You’re probably doing something similar already, and it works exactly how you’d expect:

var twoCities = new Book(
    "It was the best of times, it was the worst of times . . . ");

twoCities.read();
// It was the best of times, it was the worst of times . . . 

twoCities.getLength();
// 58

twoCities instanceof Book;
// true

The payoff is there’s very little you have to add – and only on the subclass side – to set up and use inheritance:

(function(){

    this.Diary = function(owner) {
        //Call parent constructor.
        Book.call(this, "Personal Diary of "+owner);
    };
    //Set up the prototype chain, constructor, and parent access.
    function Prot(){ this.constructor = Diary; }
    var base = Prot.prototype = Book.prototype;
    var prot = this.Diary.prototype = new Prot();

    prot.write = function(words) {
        this.words += "\n\n"+words;
    };

    prot.read = function() {
        this.write("Today I will re-read my diary.");
        return base.read.call(this);
    };

}).call(this);

One line in the child constructor calls the parent constructor (if you need it). Two lines plus an extension to an existing line set up the prototype chain and constructor while giving easy access to overridden methods. All of it’s done with short, flat, straight-line code.

It’s so clear, it almost makes the requirements it’s fulfilling seem sensible: The prototype’s prototype has to be the parent .prototype, and the prototype’s .constructor has to be the child constructor.

Now you have class-based single inheritance:

var secretDiary = new Diary("Brian");
secretDiary.write("Wrote a blog entry about JavaScript today.");
secretDiary.read();
// Personal Diary of Brian
//
// Wrote a blog entry about JavaScript today.
//
// Today I will re-read my diary.

secretDiary.getLength();
// 99

secretDiary instanceof Book;
// true

secretDiary instanceof Diary;
// true

secretDiary.constructor == Diary;
// true