JavaScript Object Oriented Programming – Prototypal Inheritance
July 21st, 2010 by JorisO | Filed under JavaScript.![]()
Although conceptually simpler than classical model – the prototypal model offers much more flexibility in the implementation of inheritance, making it easier for for a variety of more complex code reuse patterns to evolve.
D. Crockford is often quoted as referring to JavaScript as being conflicted in it’s protypal nature. According to Crockford JavaScript’s implementation of the prototype mechanism is somewhat obscured by having a pseudoclassical extra level in that objects are created by constructor functions:
When a function object is created the Function Constructor that produces the function object runs some code like this:
this.prototype = {constructor:this}
The new function object is given a prototype property whose value is an object containing a constructor property whose value is the new function object.
(JavaScript: The Good Parts – 2008 – p.47)
In Crockford’s view the constructor property is not useful and it is only the prototype object that is important. The prototype object is where inherited properties and methods are to be stored.
When a function is invoked with the ‘new’ prefix, this influences the way in which it is executed. Putting “new” in front of a function call is referred to as ‘calling a function in a constructor context’. When this is done the JavaScript engine:
1. creates a new empty object,
2. sets it’s prototype property to indicate that the empty object’s prototype is the function just called,
3. prepares to execute the called function, passing in the empty object as ‘this’,
4. executes the function,
5. returns the object.
for more details see for instance http://trephine.org
This implies that the ‘this’ keyword refers to the newly created object. If you omit the ‘new’ prefix the ‘this’ keyword will actually refer to the global object or the object the function was called from which in most cases will mean you’ll be messing about in the global scope.
To create an object that we will use as parent object for other object we simply take a function and add to it’s prototype:
var Vehicle = function (title){
this.title = title;
}
Vehicle.prototype.getTitle = function(){
return this.title;
}
To have an object inherit from the Vehicle object we define a new function and set it’s prototype to a new Vehicle instance, like so:
var Bike = function (title){
this.title = title;
this.wheels = 2;
}
Bike.prototype = new Vehicle();
In Crockfords methodology an extra function is defined to clone the objects that we wish to inherit from without having to use the new keyword, which he feels is “pseudo-classical”.
This function should look something like this:
var clone = function (obj){
function Fu(){}
Fu.prototype = obj;
return new Fu();
}
and is used like so:
var Bike = Clone(Vehicle); Bike.wheels = 2;
Asymmetry
An often confusing difference between the classical and prototypal models of inheritance lies in the fact that an object clone is not a fully independent copy of it’s prototype object. Bike.title will in the previous example refer to the shared Vehicle.title until you redefine Bike.title specifically for the Bike object. This makes for more memory efficiency but does call for greater care when modifying an objects properties. It’s very easy to forget this and accidentally modify values and methods directly on the prototype object. You can use the hasOwnProperty method to distinguish between the inherited members and the object’s actual members.
[...] Ideally however, one would not try to revert to the classical model and instead try to take full advantage of the possibilities offered by the prototype based syntax. For some ideas on how to do this see the next article on Inheritance in JavaScript [...]