In the 5th edition of my book, I propose a convention for constructor chaining:
- When you define a class B as a subclass of A, set B.prototype.superclass=A
- Then, in the constructor B(), you can chain to the superclass constructor with the natural syntax this.superclass()
Reader Bruce Wallace has just pointed out a serious flaw in this approach: you can only use it once. If you use this trick twice in the same inheritance hierarchy, you end up with infinite recursion. (If you don't see why, you can try to work out an example that includes C as a subclass of B. Or just forget it, since I think I have a better approach below.)
I'm feeling pretty embarassed to have suggested this defective method of chaining, and to have committed my suggestion to print! However, I hope to make up for it by proposing a better alternative. Here is my new convention:
- First, define the following function:
function super(o, args) { if (args.callee.superclass) return args.callee.superclass.apply(o, args); } - For each constructor B that subclasses A, set B.superclass=A;
- Do the same thing if a method of B overrides a method of A. For example:
B.prototype.toString.superclass = A.prototype.toString;
- In the B() constructor, chain to your superclass constructor like this:
super(this, arguments)
- And in a method like B.toString(), chain to A.toString() with exactly the same syntax.
This works because arguments.callee is the function that is currently running. Note that this chaining convention passes all the arguments of the subclass constructor or method to the superclass constructor or method, even if some of them are unused. So it won't work if a subclass constructor expects its arguments in a different order than the superclass constructor.
Note that the work of setting the superclass property on constructors and methods can be done by a suitable class definition utility method (such as example 9-10) in my book. This means that when writing your constructors and methods, you don't have to worry about linking the chain together; you can just call the super() method whenever you want to.
Anyone see any flaws in this approach? Comments? Suggestions? There is a simple test case defining a class hierarchy C extends B extends A below, but I haven't tried to test this extensively yet, and I''ve only run it in Firefox. Firefox is letting me use the function name "super" even though that is one of the identifiers that is unused but nominally reserved by ECMAScript v3. I choose super because Java uses that, but "chain" would probably be a safer choice.
Here is my test code:
// Magic constructor and method chaining function
function super(o, args) {
if (args.callee.superclass)
return args.callee.superclass.apply(o, args);
}
// Class A
function A(a) { this.a = a; }
A.prototype.toString = function() { return this.a + "" };
// Subclass B
function B(a, b) {
super(this, arguments);
this.b = b;
};
B.superclass = A;
B.prototype = new A();
B.prototype.toString = function() {
return super(this, arguments) + this.b;
};
B.prototype.toString.superclass = A.prototype.toString;
// Sub-subclass C
function C(a,b,c) {
super(this, arguments);
this.c = c;
}
C.superclass = B;
C.prototype = new B();
C.prototype.toString = function() {
return super(this, arguments) + this.c;
}
C.prototype.toString.superclass = B.prototype.toString;
// Create an instance of C and call toString() should display "123"
var c = new C(1, 2, 3)
alert(c.toString());



