-
Notifications
You must be signed in to change notification settings - Fork 38
Getting Started
Although augment is a simple seven line function it is packed with features. It can be used for:
- Classical inheritance in JavaScript.
- Prototypal inheritance in JavaScript.
- Creating singleton instances.
- Creating modules.
We'll start with the type signature of augment:
augment :: Function | Object // A base class constructor or prototype
-> Function // The definition of the new class or prototype
-> ... // A bunch of other optional arguments
-> Function | Object // Return a new class or prototypeNow we'll use augment to create a simple Shape data type:
var extend = augment.extend;
var Shape = augment(Object, function () {
this.Circle = extend(this, {
constructor: 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, {
constructor: 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 Shape inherits from Object.prototype while Circle and Rectangle inherit from Shape. Creating nested derived classes using augment is simple. Now let's create some instances:
var circle = new Shape.Circle(0, 0, 10);
var rectangle = new Shape.Rectangle(0, 0, 8, 6);
alert(Shape.isPrototypeOf(circle)); // true
alert(circle instanceof Shape.Circle); // true
alert(circle.area()); // 314.1592653589793
alert(Shape.isPrototypeOf(rectangle)); // true
alert(rectangle instanceof Shape.Rectangle); // true
alert(rectangle.area()); // 48.0From the above code we learn the following:
- It doesn't matter whether the base class is a constructor or the prototype of the constructor. The output will always be the same. For example we could have used
Object.prototypein place ofObjectand it would have made no difference. - Inside a class
thisrefers to the prototype of the class. Hence we can useaugmentit to create nested derived classes. - If a class defines a
constructorproperty then the constructor is returned. Otherwise theprototypeis returned. HenceShapeis an object whileCircleandRectangleare functions. - The
constructorproperty need not be a function. However it's best if you only use it as a function.
As you can see although augment is so simple yet it is very powerful. It's prototypal nature disguised as classes allows you to easily create Algebraic Data Types from functional languages. For example the above Shape data type would be written in Haskell as:
data Shape = Circle Double Double Double
| Rectangle Double Double Double Double
area :: Shape -> Double
area (Circle _ _ r) = pi * r * r
area (Rectangle x1 y1 x2 y2) = abs $ (x2 - x1) * (y2 - y1)
main = do
print . area $ Circle 0 0 10
print . area $ Rectangle 0 0 8 6Using augment promotes modularity. It encourages you to create separate files for different data types. Exporting them is very easy. For example here's how you would export the Shape data type:
if (typeof define === "function" && define.amd) define(Shape);
else if (typeof module === "object") module.exports = Shape;In the case of browsers Shape is already a global (declared as a var). Hence you don't need to export it. Thus augment allows you to easily modularize your programs into various "class" files.
This is all you need to know to get started with augment. Algebraic Data Types go a long way. In the coming articles you can learn more about the following:
- Overriding base class methods.
- Calling overridden base class methods.
- Calling the base class constructor for initialization.
- Using
augmentto create modules and singleton instances. - True prototypal inheritance using
augment.