JavaScript Inheritance Patterns

JavaScript a very slippery Object Oriented language. Functions are actually objects. A total paradigm shift from other languages like Java and PHP.

There are many ways to "create objects", some are more economical and efficient than others, while some seem very complex.

Functional

We can set up a function that acts like a constructor function, but without having to use the "new" keyword. The function creates objects, applies a prototype, initialises, and then return the objects. This is basically a factory method. The constructor conventions are the same in that we capitalise the function.

var Vehicle = function () {
  var vehicleInstance = Object.create();
  vehicleInstance.make = "Unknown";
  vehicleInstance.getMake () {
     return this.make;
  }
  return vehicleInstance;
}

The immediate thing that is not great about this method is that each method is created anew in each instance.

This leads us to sharing these methods.

Functional Shared

In order to get around recreating methods for each new object, we can add methods as references using an extend function.

var Vehicle = function () {
  var vehicleInstance = {};
  extend(vehicleInstance, vehiclePrototype);
  vehicleInstance.make = "Unknown";
  return vehicleInstance;
}

function extend (obj1, obj2) { var key; for (key in obj2) { obj1[key] = obj2[key]; } }

var vehiclePrototype = { function : getMake () { return this.make; } }

I think it looks a little messy though.

Prototypal

This is one step closer to classical inheritance. In this method we are making use of Object.create to create a new object and add its intended prototype as a parameter.

var Vehicle = function () {
  var vehicleInstance = Object.create(vehiclePrototype);
  vehicleInstance.make = "Unknown";
  return vehicleInstance;
}

var vehiclePrototype = { function : getMake () { return this.make; } }

Pseudo classical

JavaScript is a prototypal language, meaning that objects inherit from other objects, and not classes. The difference between a constructor function and a "usual" function, is how the function used. To use a function as a constructor function you would use the "new" keyword. An object is returned, with its prototype set to the function object, and the constructor property on the prototype is set to the function. Sounds complex! It is! However, using this pattern is great as it promotes economical code use and doesn't clutter the namespace.

var Vehicle = function () {
  this.make = "Unknown";
}

Vehicle.prototype.getMake = function () { return this.make; }

I had an interview recently and the lead developer asked me if I preferred "classical" or "prototypal" inheritance in JavaScript. I was like "huh?" Turns out he thought the es6 class is something different to prototypal inheritance. Classes are syntactic sugar around prototypal inheritance (check it out at Mozilla). Needless to say I declined that position.

Resources