I'm rewriting a JavaScript project, and I want to be able to use object oriented methodologies to organize the mess that the current code is. The main concern is that this JavaScript is supposed to run as a widget inside 3rd party websites and I can't have it conflicting with other JavaScript libraries that other websites may use.
So I'm looking for a way to write "class-like" inheritance in JavaScript that has the following requirements:
- No external libraries or things that would conflict with an external library (that precludes copy&paste from an external library).
- Minimalistic - I don't want the support code to be larger then a few lines of code and I don't want the developers to need a lot of boiler-plate every time they define a new class or methods.
- Should allow for dynamically extending parent objects so that child objects see the changes (prototype).
- Should allow for constructor chaining.
- Should allow for
super
type calls. - Should still feel JavaScript-ish.
Initially I tried to work with simple prototype chaining:
function Shape(x,y) {
this.x = x;
this.y = y;
this.draw = function() {
throw new Error("Arbitrary shapes cannot be drawn");
}
}
function Square(x,y,side) {
this.x = x;
this.y = y;
this.side = side;
this.draw = function() {
gotoXY(this.x,this.y); lineTo(this.x+this.side, this.y); ...
}
}
Square.prototype = new Shape();
And that solves requirements 1, 2 and 6 but id does not allow super calls (new functions override parent functions), constructor chaining and dynamically extending a parent does not provide the new methods to a child class.
Any suggestions will be welcome.
You can use functional pattern proposed by Crockford in his book "JavaScript the good parts". Idea is use closore to make private fields, and use previleged function to access to these fields. Here is one of solutions which meet your 6 requirements:
OK, the trick with reproducing a class/instance-style system in JavaScript is that you can only use prototype inheritance on the instances. So you need to be able to make a ‘non-instance’ instance that is only used for inheritance, and have an initialiser method separate from the constructor function itself.
This is the minimal system I use (before adding frills), passing a special one-off value into the constructor to have it construct an object without initialising it:
The use of
new Function()
is a way to avoid forming an unnecessary closure over subclass(). You can replace it with a prettierfunction() {...}
expression if you prefer.Usage is comparatively clean, and generally like Python-style objects only with slightly clumsier syntax:
Monkey-patching a builtin (Function) is a bit questionable, but makes it pleasant to read, and no-one's likely to want to
for...in
over a Function.Douglas Crockford has good articles on both classical and prototypal inheritance in Javascript, which should make good starting points.
Also Crockford-inspired, but I had good experiences with what he calls "functional inheritance" using "constructor functions". YMMV.
UPDATE: Sorry, I forgot: you still need to augment Object with a
superior
method to get nice access to a super method. Not a good fit for you, probably.The most common pattern I found when researching this question is described on the Mozilla Developer Network. I've updated their example to include a call to a superclass method and to show the log in an alert message:
I'd suggest the following pattern which makes use of a
clone
function to inherit from the protoypes and not instances:It's important that methods reside in the prototype (which is as it should be anyway for performance reasons) so you can call the methods of a super class via
With some syntactic sugar, you can make JS look like a classical class-based language: