Javascript takes a lot of flack for being prototypal vs class based which leads a lot of developers to incorrectly assume that OOP techniques like constructor chaining and inheritance aren’t possible. This couldn’t be further from the truth; the real issue is that Javascript didn’t used to include any native OOP style methods. Luckily however javascript still provided us enough power to be able to build these methods and techniques ourselves. It gets even easier when you are able to use ES5 Javascript; or for cross browser support use a framework like YUI which adds in the OOP methods missing from Javascript which I’ll be covering in a follow up post.

The first step is to understand that a constructor in Javascript is simply a function that you call with the word new. In the following example we are creating a function called Car, creating a color property on each instance of Car with the this special property, then creating a new instance of that function which is being assigned to the mustang variable.

function Car() {
    this.color = "red";
}
var mustang = new Car();
console.log(mustang.color); // Prints `red` to the console

The new keyword is very important when creating constructors in javascript. Without new Car will be executed and this will point to window creating global variables, and it’s return value will be assigned to mustang. In this case mustang will be undefined and if you try and access any properties on it your script will grind to a halt.

To be able to chain these constructors we will use one of two Javascript methods; call(), or apply(). These allow us to call another method in javascript but specify the scope to which it executes.

A common example to illustrate inheritance is creating a character in a video game.

function Baddie() {
  // Set up the baddies defaults
  this.level = 1;
  this.hitPoints = 100;
  this.name = "Baddie";
}

function Spider() {
  // Executing Baddie with it's context set to Spider
  // because we used `this` it now assigns it's properties
  // level, hitPoints, and name to the Spider instance.
  Baddie.apply(this);
  this.color = "red";
  this.legs = 8;
}

var regularSpider = new Spider();

console.log(regularSpider.level); // Prints `1` to the console
console.log(regularSpider.legs); // Prints `8` to the console

So here we have created two constructor functions, Baddie and Spider. The important line here is Baddie.apply(this); which executes Baddie in the context of Spider - adding those properties to the Spider instance. Using this technique you can chain as many constructors together as you like.

This is great but what if we need to create many different types of Spiders; we need a way to pass data from our instantiation down the stack.

function Baddie(config) {
  // Set the baddie defaults using the
  // supplied configuration values or the defaults
  config = config || {};
  this.level = config.level || 1;
  this.hitPoints = config.hitPoints || 100;
  this.name = config.name || "Baddie";
}

function Spider(config) {
  // This time we pass in a second paramter which
  // is the configuration object, or an empty
  // object if none was supplied
  config = config || {};
  Baddie.apply(this, arguments);
  this.color = config.color || "red";
  this.legs = config.legs || 8;
}

var regularSpider = new Spider(),
    // Pass a configuration object into the constructor
    superSpider = new Spider({
      level: 10,
      hitPoints: 10000,
      name: "Super Spider",
      color: "yellow",
      legs: 16
    });


console.log(regularSpider.level); // Prints `1` to the console
console.log(superSpider.level); // Prints `10` to the console
console.log(regularSpider.color); // Prints `red` to the console
console.log(superSpider.color); // Prints `yellow` to the console

With this example we are creating a super spider by passing a configuration object into the Spider constructor. For this to have any effect down the chain we need to add a second parameter to our apply() call. arguments is a special variable available in all functions which is an array-like object corresponding to the values passed to a function. This allows us to pass everything that was in the configuration object down to the next constructor.

If you remember a little earlier I mentioned we could also use the call() function. This function accepts an argument list instead of an array of values. So if you prefer to pass in values in this matter you would use call() instead of apply().

The last topic I want to touch on in this post is private properties and constructor methods using chained constructors. They are done pretty much exactly how you would assume coming from other languages but I’m going to illustrate the syntax just to drive it home. I have trimmed down the code a bit in this example to highlight the parts related to this topic.

function Baddie(config) {
  var id = "abc";

  // Code removed for brevity

  this.getId = function() {
    return id;
  };
  this.setId = function(newVal) {
    id = newVal;
  }
}

function Spider(config) {
  Baddie.apply(this, arguments);
  // Code removed for brevity
}

var spiderOne = new Spider(),
    spiderTwo = new Spider();

console.log(spiderOne.getId()); // Prints `abc` to the console
spiderOne.setId('123');
console.log(spiderOne.getId()); // Prints `123` to the console
console.log(spiderTwo.getId()); // Prints `abc` to the console

So as you can see in the Baddie function I created a local variable called id and assigned it a default value. I also created very basic getter and setter methods so that you can access this variable from outside of the function. Further down in the script I instantiate two completely separate spiders - they even have their own private id variable which is illustrated when I set it to 123 for spiderOne, but spiderTwo is still the default.

In coming posts I will be covering prototypal inheritance, YUI OOP, and new related Javascript methods but I’ll be sure to link them here. Thanks for reading! If you have any questions or comments you can comment below, or mention me @fromanegg. Till next time!