...and then it crashed

Programming the web with Python, Django and Javascript.

Javascript object inheritance isn't complicated

Javascript’s method of object inheritance causes a lot of confusion, even amongst experienced programmers. This is largely because it doesn’t follow the classical inheritance pattern found in many other popular programming languages, suce as Java, PHP, Python and Ruby.

Instead, Javascript uses a prototype inheritance pattern, which is a little different. To confuse matters, many frameworks attempt to “fix” Javascript inheritance by making it work more like classical inheritance. The end result is a mess.

Thankfully, Javascript inheritance is actually pretty easy!

Defining a new class

Let’s define a new class, Animal. Animals have a name, an age, and can make a noise.

1
2
3
4
5
6
7
8
9
10
// Define the Animal constructor.
function Animal(name, age) {
    this.name = name;
    this.age = age;
}

// Define the makeNoise method.
Animal.prototype.makeNoise = function() {
    return "Snuffle";
}

You can instantiate an Animal like this:

1
2
var animal = new Animal("Fluffy", 5);
animal.makeNoise();  // => "Snuffle"

Inheriting from this class

Let’s now make a Dog, which is like an animal, but also has a breed, and makes a different noise.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Dog(name, age, breed) {
    // Call the parent constructor.
    Animal.call(this, name, age);
    // Add dog-specific constructor logic.
    this.breed = breed;
}

// Extend the Animal class.
Dog.prototype = Object.create(Animal.prototype);

// Extend the makeNoise method.
Dog.prototype.makeNoise = function() {
    var parentNoise = Animal.prototype.makeNoise.call(this);
    return parentNoise + "... Woof!";
}

You can then instantiate a Dog like this:

1
2
var dog = new Dog("Spot", 5, "Golden Retriever");
dog.makeNoise();  // => "Snuffle... Woof!"

What about private methods and properties?

While it’s possible to implement something similar to private methods and properties, it probably isn’t worth the time and effort (and performance penalty) of using them. Simply prefixing non-public methods and properties with an underscore is a good way of indicating they they’re not part of the public API.

What about interfaces?

Interfaces can be useful, but Javascript doesn’t support them. In any case, they would add to the download size of your code.

What about prototype.constructor?

If your code depends on prototype.constructor being set, then you can use the following helper method instead of calling Object.create() directly.

1
2
3
4
5
6
7
8
9
10
function inherits(child, parent) {
    child.prototype = Object.create(parent.prototype, {
        constructor: {
            value: parent,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
}

In reality, prototype.constructor isn’t very useful, so it’s probably best to just call Object.create() directly.

Using inheritance in your code

Javascript code has an unfortunate habit of turning into a mess of nested callbacks and copy-and-paste logic. Defining a hierarchy of helper classes is just one of the many techniques that allow you to write modular, maintainable code.

For example, consider building:

  • A hierarchy of Javascript form validation classes. These could all inherit from a base Validator class that implements basic checks for required fields. Subclasses could provide integer validation, date validation, password length validation, etc.
  • A set of models that map to server-side database objects. These could all inherit from a common Model class that contains the HTTP syncronization logic.
  • A related set of AngularJS services. Data-driven services could inherit from a base Service class that provides logic for updating data within bound scopes.

Comments