JavaScript Inheritance
JavaScript inheritance can be done dozens of different ways. One of the major plusses of the language is that it’s flexible enough to allow many possible paradigms. However, this also turns into a major language detractor, since everyone does it just a little differently. Here are a couple and some reasons I lean one way most of the time.
First, there’s a functional pattern. I actually like this a lot. Probably because I’ve written way too much Scheme in my time, but it’s elegant and, through functional scope, provides privacy otherwise lacking in JavaScript.
For example:
var make_rectangle = function(length, width) {
// length, width in private scope
var area = function() {
return length * width;
};
return {
area: area
};
};
var make_square = function(length) {
return make_rectangle(length, length);
};
var r = make_rectangle(1, 2);
var s = make_square(2);
r.area();
s.area();
This is sometimes called the Module pattern and sometimes uses constructors with the new keyword, but that all amounts to the same thing: a function that generates an object.
The functional pattern is great, and I like it for lots of things but it has significant drawbacks. Privacy is rarely really needed and blocks lots of fun extensions once the object is created (e.g. r.perimeter = function() { return 2*this.length + 2*this.width; };) The subtle drawback is the performance hit it entails, which I will come back to.
Then there’s a classical-styled inheritance pattern. Which has it’s drawbacks but has grown on me in recent months.
function Rectangle(length, width) {
this.length = length;
this.width = width;
};
Rectangle.prototype.area = function () {
return this.length * this.width;
};
function Square(length) {
/* could use parent constructor here, but requires some more work. */
this.length = this.width = length;
};
Square.prototype = new Rectangle();
var r = new Rectangle(1, 2);
var s = new Square(2);
r.area();
s.area();
This is pretty straightforward and understandable for someone coming from the OO world of doing things. Rectangle constructs an object that has a length and a width. The next line adds a function to it’s prototype. Square constructs similarly. And sets it’s prototype to an instance of Rectangle (it’s actual data doesn’t matter; so here, length and width are undefined).
Now this approach has it’s drawbacks too. There’s no easy way to call a parent’s constructor. This can be buttered over with some convenience functions if necessary. And the new keyword has it’s problems: without the new, calls to Rectangle and Square have this bound to the global namespace which can cause all kinds of crazy problems. As Crockford says, “There is no compile warning, and there is no runtime warning.” This used to bother me, but I’ve learned to live with lint. A capitalized function must always get called with new, done and done. Besides, if you’re extra paranoid, there’s always:
function Rectangle(length, width) {
if (!(this instanceof Rectangle)) {
return new Rectangle(length, width);
}
this.length = length;
this.width = width;
}
But this also has it’s advantages. For example, not only can I now extend individual objects, but I can also add functionality to the prototype itself. For example:
r.perimeter = function () { return 2*this.length + 2*this.width; };
r.perimeter();
Or:
Rectangle.prototype.perimeter = function () { return 2*this.length + 2*this.width; };
r.perimeter();
s.perimeter();
Which otherwise, the privacy would block. The subtle advantage is that the classical actually performs much better than our first pattern. A quick profile shows:
>>> function exercise_classical() {
for (var i=0; i<100000; i++) {
(new Rectangle(1, 2)).area();
}
};
>>> function exercise_functional() {
for (var i=0; i<100000; i++) {
make_rectangle(1, 2).area();
}
};
function calls time average make_rectangle 100000 418.666ms 0.004ms Rectangle 100000 95.361ms 0.001ms
A pretty big difference and a huge factor for objects in tight loops.
The classical pattern is much faster, because it’s doing much less. It makes one area function assigned to Rectangle’s prototype and the language delegates all calls to it up to that instance with the correct data bound to this. The functional pattern is making a new area function for every object. And assigning it to it’s own property. Not only wasting a bunch of time, but also memory.
JavaScript is fun. It lets you do all this any way you choose. Which is a blessing and a curse. My choice tends to change fairly frequently.

