Why Prototypal Inheritance Matters
Aadit M Shah | Why Prototypal Inheritance Matters
Argues that classical inheritance is not suitable for JavaScript
- you cannot do
var author = new Person.apply(null, ["Aadit", "Shah"]);
– you cannot callapply
onnew
constructor call - the
new
keyword was added to make appeal to Java developers
explains prototypal inheritance
Object.create
patterna nice pattern to simplify object creation and initialisation:
var rectangle = {
create : function ( width, height ) {
var self = Object.create( this );
self.height = height;
self.width = width;
return self;
},
area : function () {
return this.width * this.height;
}
};
var rect = rectangle.create( 5, 10 );
alert( rect.area() );
compare this with the constructor pattern
function Rectangle ( width, height ) {
this.height = height;
this.width = width;
}
Rectangle.prototype.area = function () {
return this.width * this.height;
};
var rect = new Rectangle( 5, 10 );
alert( rect.area() );
the above object creation and initialisation pattern can be further abstracted with the extend
implementationA typical
extend
pattern in JS:
Object.prototype.extend = function ( extension ) {
var hasOwnProperty = Object.hasOwnProperty;
var object = Object.create( this );
for ( var property in extension )
if ( hasOwnProperty.call( extension, property ) ||
typeof object[ property ] === "undefined" )
object[ property ] = extension[ property ];
return object;
};
then the create
method can be simplified to this:
var rectangle = {
create : function ( width, height ) {
return this.extend( {
height : height,
width : width
} );
},
area : function () {
return this.width * this.height;
}
};
var rect = rectangle.create( 5, 10 );
alert( rect.area() );
then explains the [[proto]] chainInheriting from multiple prototypes
need to extend
extend
to copy from multiple prototypes. You could just call extend
(with the above implementation) several times on your object, modify to extend
method to accept multiple parameters.a basic pattern:
Object.prototype.extend = function () {
var hasOwnProperty = Object.hasOwnProperty;
var object = Object.create( this );
var length = arguments.length;
var index = length;
while ( index ) {
var extension = arguments[ length - (index--) ];
for ( var property in extension )
if ( hasOwnProperty.call( extension, property ) ||
typeof object[ property ] === "undefined" )
object[ property ] = extension[ property ];
}
return object;
};
arguments
is a standard JavaSciprt property that holds all the parameters passed to a function. In this case it holds several objects that we want to extend our object with.shows an example where you can create an
eventEmitter
object and later extends the rectangle
object with eventEmitter
mixins
notes that
eventEmitter
doesn't (and shouldn't)
have
a create
method. You don't want to create an object that only delegates to eventEmmitter
, second, it would override create
method that already exists. These kinds of objects are called mixins.
blueprints
define
eventEmitter
as a function rather than an object so you can have closures to store private variables.it can have private variables (e.g.
events
) and the methods are defined as this.on = function (event, listener){//...}
then in your
create
function you can call
this function to add the eventEmitter
methods:create: function(){
//...
eventEmitter.call(self);
// ...
fixing the instanceof operator
many JavaScript programers prefer the constructor pattern since in this case the
instanceof
operator returns true
this can be corrected by adding the
Object.prototype.instanceof
operator that uses Object.getProtoypeOf
internally.