If you come from a classical, traditional OO programming language and you stumbled on this famous article by Douglas Crockford on JavaScript inheritance, you are probably thinking the worst thoughts ever conceived on JavaScript. Don't get me wrong: this article is superb and its author a first-class JavaScript programmer, but surely he doesn't make life easy for non-JavaScript programmers. Let's face it: it's complicated. Yes, it's stimulating, precise, consistent, interesting but, hey, still complicated. Furthermore, this article also describes four sugar methods for dealing with inheritance that, only in theory, should explain inheritance better. Instead, they get things even more complicated to follow. In this post I'll try to explain this article in simpler terms.
First, all object methods used in this example are created through an helper method obtained by augmenting the prototype
property of the core Function
object. JavaScript is a dynamic language that allows for the modification of every object, including the core ones.
Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; };
method
accepts two parameters: name
, which represents the name of the newly created method, and func
, the function body which makes up the method itself. But why Function
? Because this core object in JavaScript has a double usage: it can be either used as an object constructor or as a normal, procedural function. So if you extend this core object in this way, you can first create an object and then adding a new method to it:
function Parenizor(value) { this.setValue(value); } Parenizor.method('setValue', function (value) { this.value = value; return this; }); Parenizor.method('getValue', function () { return this.value; }); Parenizor.method('toString', function () { return '(' + this.getValue() + ')'; });
Now the object Parenizor
has three methods defined through Function.method()
, namely setValue()
, getValue()
and
toString()
. This happens because functions are objects in JavaScript or, more precisely, are first-class objects, so augmenting the core Function
object will be reflected on all function objects.
Then inheritance. To be honest and practical, in JavaScript all you should know about inheritance can be summarized in the following code:
function Parent() { this.property = 'Test'; this.method = function() { return this.property; }; } function Child() { this.property2 = 'Test 2'; } Child.prototype = new Parent();
By associating the prototype
property of the child object to an instance of the parent object, you've actually extended the child object with the parent object. This is the only way of handling inheritance which is indirectly mentioned in the ECMAScript specifications (the famous page with the prototypal diagram, if you've read it).
Crockford extends this basic way of handling inheritance by proposing an inherits()
method. However, a simpler solution has been explained in this article by Harry Fuecks. I recommend you to read this article because it provides a clear explanation to the problem.
In short, trying to make JavaScript work like a classical OO programming language is surely the best thing to do for a JavaScript programmer and also the most interesting and stimulating thing for me. Instead, it's better to keep things simpler if you are not a JavaScript programmer and, most of all, if you come from a classical OO programming language.