Prototypal Inheritance: One Size Does NOT Fit All

There is the prevailing attitude within the JavaScript community that prototypal inheritance will fit for all use cases where object-oriented design is required. However, in real world application development, this isn’t quite so ideal. First, let’s examine the history.

JavaScript, as a language, was designed by Brendan Eich for Netscape back in 1995. He was tasked to design a language that looked like Java, the popular programming language of that time with its promise of cross-platform compatibility. Thus, JavaScript was born… in just ten days. However, there was one problem with Java: classes. Why buck the trend and omit classes if one was trying to emulate the most popular programming language of the time? Why, when tasked with creating a familiar language, would one opt for a design that was alien to contemporary programmers?

To answer this, let’s rewind the clock to 1995. The technology industry is booming, the personal computer industry is finally reaching critical mass, and class-based OOP was hailed as the end-all be-all of programming. I still remember the specs on my computer at that time: 133 MHz Pentium, 8MB RAM, 15″ CRT monitor, Windows 95.

One year earlier, the Gang of Four “Design Patterns” book was published. This landmark text described software design patterns for OOP. Amongst the various patterns introduced, there were a few patterns focused on optimization and conservation of system resources such as the Flyweight Pattern and the Prototype Pattern.

To explain the prototype design pattern in-depth, let’s use examples: where it’s appropriate, and where it isn’t.

Proper Use Case: RTS (Real-Time Strategy)
Imagine that we are developing a RTS (real-time strategy) game. Ideally, the game should support thousands of soldiers moving and interacting simultaneously.

[js]
function Soldier() {
}
Soldier.prototype = {
moveTo: function(newX, newY) {
},

getX: function() {
},

getY: function() {
}
};

var soldier1 = new Soldier({
x: 50
, y: 50
, hp: 100
, attackPower: 5
});
var soldier2 = new Soldier({
x: 50
, y: 60
, hp: 80
, attackPower: 3
});
[/js]

In this scenario, every “Soldier” instance shares common properties: moveTo, getX, getY. The Prototype Pattern is a creational pattern. The core idea is to make instantiation as cheap as possible. Furthermore, if every “Soldier” instance carried its own moveTo, getX, getY methods as with “classical” inheritance, my poor 8MB RAM on my 1995 machine would explode.

However, if you’re using prototypal inheritance where it does not make sense to be sharing state or behaviors on modern computer hardware then you’re abusing it. Well, perhaps using the word “abuse” is a tad harsh because the reality has been that JavaScript, as a language, just never supported class-based inheritance, and all efforts by JavaScript libraries to implement classes have resulted in a mess: weird “gotchas” with the “this” keyword; wasting of brain cycles deciphering which fields are public, private, or static; the downright awkward syntax which is only a slight improvement over the spaghetti of vanilla JavaScript; pass-by-value vs. pass-by-reference Doomsday scenarios; closure voodoo without considering the negative implications (e.g. memory leaks); and so on.

As programmers, we strive to use the best tool(s) for the job. The narrow-minded and sometimes arrogant attitude within the JavaScript community suggests we aren’t using the best tools or, sometimes, even the right tools. Of course, this doesn’t apply to everyone, but there are the select few that want to dismiss programmers trained in class-based OOP that cannot wrap their heads around prototypes as being “inferior,” and the reverse is also true thus creating a vicious cycle and a culture of animosity.

With that said, it’s important to discuss when we should NOT use prototypal inheritance:

Improper Use Case: UI Libraries

[js]
var ComboBox = {
items: [
"London"
, "Paris"
],

addItem: function(newItem) {
this.items.push(newItem);
},

getItems: function() {
return this.items;
}
};
var combo1 = Object.create(ComboBox);
var combo2 = Object.create(ComboBox);
combo1.addItem("NYC");
console.log(combo2.getItems()); // [ "London", "Paris", "NYC" ]
[/js]

At the time of this writing, ExtJS 4 is arguably the preferred UI library for RIAs. What do they describe as one of their major features? A new class system.

Now it’s easy to get fanatical and argue, “Well, with prototypal inheritance, we can emulate classes by doing such and such.” Yes, you can build a class system on top of a prototypal system and vise versa, but you’re missing the point: with JavaScript, it ends up as spaghetti code. I want to be able to, at first glance, know exactly which fields and methods are private or public without having to go through all your code and closure magic. If I want to change an access modifier from public to private, I should not have to change every reference of the field in question to strip out “this”.

“But it’s all about code reuse!”

As far as I know, the argument that it’s all about code reuse was first introduced by Douglas Crockford and then subsequently regurgitated by everyone else:

“The second reason is code reuse. It is very common to have a quantity of objects all implementing exactly the same methods. Classes make it possible to create them all from a single set of definitions. It is also common to have objects that are similar to some other objects, but differing only in the addition or modification of a small number of methods. Classical inheritance is useful for this but prototypal inheritance is even more useful.” – Douglas Crockford (http://javascript.crockford.com/inheritance.html)

I’m not arguing that prototypal inheritance isn’t about code reuse – it certainly is and has been since inception. The question is: for your given situation, is there a *better way* of achieving code reuse? Would classical inheritance make more sense in your situation? What about mixins?

Remember, to paraphrase Martin Fowler, good programmers write code humans can understand!