-
Notifications
You must be signed in to change notification settings - Fork 38
Prototypal Inheritance
Although augment
is primarily used as a classical inheritance function it can also be used for prototypal inheritance. In prototypal inheritance you don't have any constructor functions. Objects simply inherit from other objects. In this respect it's very similar to Crockford's Object.create
function. To make prototypal inheritance easier let's create a base prototype called instance
which every prototype and object derives:
var instance = {
is: function (object) {
return object.isPrototypeOf(this);
},
create: function () {
return augment(this, constructor, arguments);
}
};
function constructor(args, base) {
base.init.apply(this, args);
}
The instance
prototype has two helper functions, is
and create
, which correspond to the instanceof
and new
operators respectively. So let's begin with prototypal inheritance. We'll create the same algebraic data types as we did in Getting Started:
var extend = augment.extend;
var shape = augment(instance, function () {
this.circle = extend(this, {
init: function (x, y, r) {
this.x = x;
this.y = y;
this.r = r;
},
area: function () {
return Math.PI * this.r * this.r;
}
});
this.rectangle = extend(this, {
init: function (x1, y1, x2, y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
},
area: function () {
return Math.abs((this.x2 - this.x1) * (this.y2 - this.y1));
}
});
});
As you can see the code remains largely the same. The only differences are:
- The names
Shape
,Circle
andRectangle
becomeshape
,circle
andrectangle
respectively. - The prototype
shape
now derives frominstance
instead ofObject
. - The
constructor
function is now called theinit
function.
So let's see how to use it:
var circle = shape.circle.create(0, 0, 10);
var rectangle = shape.rectangle.create(0, 0, 8, 6);
alert(circle.is(shape)); // true
alert(circle.is(shape.circle)); // true
alert(circle.area()); // 314.1592653589793
alert(rectangle.is(shape)); // true
alert(rectangle.is(shape.rectangle)); // true
alert(rectangle.area()); // 48.0
That's all that there is to prototypal inheritance. So what are the advantages of prototypal inheritance over classical inheritance?
- Since
create
is a function you can use it in conjunction withapply
. You can't usenew
in conjunction withapply
. - Forgetting to use
new
leads to unexpected bugs and global variables. It's not possible to forgetcreate
. - Prototypal inheritance is cleaner. It teaches you that there's nothing special about
.constructor
or.prototype
. In fact you don't really need constructor functions for inheritance in JavaScript. All you do need are objects.
If you want to know more about prototypal inheritance then read my blog post on Why Prototypal Inheritance Matters.