Javascript Objects and Inheritance with Node.js

It has been years since I was particularly interested in the Javascript language. At the time it was slow, and I really felt that the virtual machine environment of Java provided everything I could possibly need in developing software – needless to say I didn’t spend much of that time doing front end web page development.. Recently however I have come across the Node.js system (here) and I’ve been enticed to dive more deeply into a language I had previously dismissed. I will write more about Node itself later, but for now I wanted to explore a bit about objects in Javascript.

Jumble of Objects

The fun thing about objects in Javascript is that they are completely mutable – which is to say, the ‘class’ is not static, it can change during execution. Additionally, objects themselves can define new properties and methods that are specific to them.

In the traditional class model that I have been most familiar with, constructs called classes are defined which provide the definition of the properties and methods. An object then is a new instance of the class – it contains the data specific to that instance, but it does not define additional data elements (properties if you will) or methods which may be called on the object – it can only do what it is defined to do by its class. Inheritance is handled at the class level, and the object remains an instance of a particular class.

In Javascript however we have the opportunity to do prototypal inheritance. In this scenario, object structure, not just data, is mutable. So if I happen to define a car object, I can make a bunch of car objects which will have the same properties. I may then directly add additional properties or methods to these ‘children’ without the need to rely on a class structure. Here’s an example of creating a new child object:

// This defines an object
function objectDefinition() {
	// Do nothing
}
// Now we make an instance of it
var myObject = new objectDefinition();
myObject.universalAnswer = 42;
 
util.log(myObject.universalAnswer);

This code when executed in node will log the number 42 to the console (if using a browser you could easily utilize alert instead). Now myObject, which is an instance of parentObject, has this special property (universalAnswer). However, other instances will not have this special property – for instance, this will fail:

// This defines an object
function objectDefinition() {
	// Do nothing
}
// Now we make an instance of it
var myObject = new objectDefinition();
myObject.universalAnswer = 42;
 
var anotherObject = new objectDefinition();
 
util.log(anotherObject.universalAnswer);

Now I could put this property up inside objectDefinition – to do this, I must define it inside the constructor function itself. Like so:

// This defines an object
function objectDefinition() {
	this.universalAnswer = 42;
}
// Now we make an instance of it
var myObject = new objectDefinition();
 
var anotherObject = new objectDefinition();
 
util.log(anotherObject.universalAnswer);
 
util.log(myObject.universalAnswer);

This code will log the number 42 twice, once for anotherObject and then for myObject, as they both have now inherited the property from objectDefinition. However, we just got done talking about how mutable all the classes are – what if I wanted to add this property later, after objectDefinition was already defined, and have all of the instances inherit it?

I could try something like this, but it would fail to achieve the desired result:

objectDefinition.universalAnswer = 42;

To actually achieve my intent I have to leverage something called ‘prototype’. The prototype property enables us to add methods and properties to objectDefinition which will be inherited by the instances. This adjusted example works and logs 42 twice:

// This defines an object
function objectDefinition() {
 
}
// Now we make an instance of it
var myObject = new objectDefinition();
 
var anotherObject = new objectDefinition();
 
objectDefinition.prototype.universalAnswer = 42;
 
util.log(anotherObject.universalAnswer);
 
util.log(myObject.universalAnswer);

Unfortunately, with our code as-is, I cannot further extend from myObject or anotherObject – that is to say, I cannot have another object inherit from myObject. This is because myObject has no constructor function. I might think ‘hey, I can just add a constructor function!’ but I have not found a clean way to do this. As such, we do need to define a sort of hierarchy a bit more intelligently if we want to have a construct with superclasses and subclasses. Let’s build such a thing here:

// This defines a "class"
function objectDefinition() {
	this.universalAnswer = 42;
}
 
// This defines the "sub-class"
function subObjectDefinition() {
	this.super = objectDefinition;
	this.super();
}
 
var myObject = new subObjectDefinition();
 
util.log(myObject.universalAnswer);

So we can see here that we are able to create an instance of subObjectDefinition because we have a constructor which can then be called by new. As such, our ‘classes’ which we wish to have object instances of and mutate via prototype must be created with constructor functions.

You’ll see here that we do something a little bit strange in subObjectDefinition(). We create a new property subObjectDefinition.super and store the objectDefinition constructor function in it. We then call this constructor function. By doing this, subObjectDefinition now has the properties defined in the objectDefinition constructor, such as universalAnswer. Alternatively in node we can do this – note that we move the property definitions to prototype, this is important as it is the prototype values which are inherited.

// This defines a "class"
function objectDefinition() {
}
objectDefinition.prototype.universalAnswer = 42;
 
// This defines the "sub-class"
function subObjectDefinition() {
}
 
util.inherits(subObjectDefinition, objectDefinition );
 
var myObject = new subObjectDefinition();
 
util.log(myObject.universalAnswer);

Some digging through the lib folder of node finds us the implementation of util.inherits, which is thus:

exports.inherits = function(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
};

Here the author is actually creating an anonymous object in between which is an instance of the super’s prototype. This chain enables us to set the child.prototype.* without altering the parent’s prototype (which would be the case if we directly assigned the prototypes to be equal).

In this way, we can define each of our classes (basically empty constructor functions), define an inheritance hierarchy, add properties and values to each of these class’s prototypes, and create instances that appropriately respect the inheritance chain for locating properties or methods to execute. With the super value, we can call (and call() or apply()) our parent methods.

That is all well and good, however one might say ‘well that does not seem very…well…prototypal’ though I suppose one would have to define what THAT means. However, I am reminded of the first programming language I ever encountered – MOO. This was a domain specific language for online multi-user virtual environments, and it utilized what I would call true object-oriented, prototypal relationships. This is as opposed to the more typical models we have above, i.e. in Java C++ etc, where CLASSES INHERIT FROM CLASSES and OBJECTS ARE INSTANCES OF A CLASS. This is to say, OBJECTS INHERIT FROM OBJECTS in what I would consider a pure object-oriented prototypal inheritance, and each customization carries down through the tree of object inheritance.

When I first learned C++, understanding that objects did not inherit from other objects in this way was probably the greatest barrier I faced – such a non-object-oriented but rather class-oriented approach took a lot of getting used to. I’ve long looked back on the simplicity of true object inheritance and hoped I might see it again elsewhere…thankfully, a fellow by the name of Douglas Crockford came up with a way to do this in JavaScript. Here is his article: Prototypal Inheritance in Javascript

I’ll let the article speak for itself, with the exception that I will provide a simple example here that shows the simplicity and power of the approach:

// Setup our object creation function, this becomes boilerplate
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
 
// Define some objects, some values, inherit away
function oldObject() {}
 
var newObject = Object.create(oldObject);
newObject.universalAnswer = 42;
 
var anotherObject = Object.create(newObject);
util.log(anotherObject.universalAnswer);

Note no super here, which can be a concern – I’ll leave it an exercise for those interested to bridge that gap.

I believe both the purist ‘objects inherit from objects’ approach shown here as well as the more classical separation of class and object as seen in Node’s implementation of util.inherits have their place. In my case I have a project for which I am most interested in this last method of inheritance, as the simplicity it brings provides some unique characteristics.

I have found inheritance in Javascript to be a construct that appears deceptively simple on the outside but which contains a tremendous amount of flexibility. I wrote this article while learning the topic myself and so look forward to comments or suggestions.

This entry was posted in Javascript, Node.js and tagged , , , , , , , , , . Bookmark the permalink.

One Response to Javascript Objects and Inheritance with Node.js

  1. Pingback: Node.js Example 12: Util Inherits | ez node.js examplesez node.js examples

Leave a Reply

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


*