Note: This post was originally written in 2008. There's a 2015 update at the bottom.
There are many different ways to achieve Object Orientation in JavaScript and the Internet is littered with examples.jQuery Uses an extend method within the super-class that allows you to add functionality onto an instance of that class, creating a kind of sub-class (although it is an object):
SuperClass.prototype = {
// ...
extend: function() {
var int_count = 0;
var arr_prop;
while ( (arr_prop = arguments[int_count++]) != null ) {
for ( var i in arr_prop ) {
this[i] = arr_prop[i];
}
}
// Return the modified object
return this;
}
}
// ...
var obj_subclass = new SuperClass();
obj_subclass.extend({
foo: 'bar',
// ...
});
This is quick and dirty but not proper OO and if you want several instances of the 'sub-class' you need to call extend on each one.
You probably already know that to add member variables/methods to a class you assign them to its prototype property. This can be one value at a time:
SuperClass.prototype.foo = 'bar';
Or a simple object can be assigned:
SuperClass.prototype = {
foo: 'bar',
x: 'y',
super_func: function() {
//...
}
}
A good way to simulate inheritance is to assign an instance of the super-class to the sub-class' prototype example here:
function SubClass() {}
SubClass.prototype = obj_super;
This means that all member variables/functions of SuperClass are now contained within SubClass' prototype.
In order to now extend SuperClass' functionality in SubClass we revert back to adding one new thing at a time with SubClass.prototype.sub_func = function() { //... }. This is fine but if you plan on adding a lot more stuff it's not ideal.
The solution I have come up with (I say "I", maybe other people do this but I can't find any mention of it on the net) is to combine the two methods above:
function SubClass() {}
SubClass.prototype = obj_super.extend({
foo: 'bar',
sub_func: function() { //... },
// ...
});
This way we are still creating a proper sub-class and inheriting the super-classes functionality whilst conveniently adding our own.
Note: You can call super-class methods directly from within the sub-class with SuperClass.prototype.super_func.call(this, arg1, arg2, argN);
Update (03/01/2015)
The above used to be how I extended 'classes' in JavaScript but these days I use a different method. Again, there are many ways to achieve JS extension, what follows is just my preference.
This method has two main requirements:
- You call the constructor of the parent inside the constructor of the child using the child's context
- You copy the parents prototype onto the child's prototype via the Object.create method
function SuperClass() { var a = 1; this.getA = function() { return a; }; } SuperClass.prototype.functionA = function() { alert('SuperClass functionA'); }; function SubClass() { SuperClass.call(this); var b = 2; this.getB = function() { return b; }; } SubClass.prototype = Object.create(SuperClass.prototype); SubClass.prototype.functionB = function() { var aPlusB = this.getA() + this.getB(); alert('SubClass functionB. a+b == '+aplusB); }; var eg = new SubClass(); eg.functionA(); // alerts "SuperClass functionA" eg.functionB(); // alerts "SubClass functionB. a+b == 3"
Now SubClass extends SuperClass. So why not use SubClass.prototype = new SuperClass();
you ask? Well there's a subtle difference between new
and Object.create()
in that the latter doesn't actually call SuperClass's constructor, it just copies the prototype so the SuperClass constructor will only get called at the time of creation of the SubClass (as we are calling it explicitly with SuperClass.call(this)
).
Note that, as with the old method from this post, the way to call SuperClass function directly is with SuperClass.prototype.functionName.call(this, arg1, argN)