In another SO question about whether to call a super-constructor or use the prototype chain the answer provided by one of the users seemed sensible but didn't work for me when I implemented it on my solution which has multiple layers of inheritance.
Here's the answer I'm referring to: https://stackoverflow.com/a/4389429/392591
So I've created a jsFiddle using this custom extend method to illustrate the problem: https://jsfiddle.net/68q7yghv/
I've added the jsFiddle code at the bottom.
In my test I've created a 4 tier class inheritance structure from baseClass through to subSubSubClass each of which (except the baseClass) use the 'extend' method to inherit from the previous sub-class. When you hit the test button I'm printing out class.baseClassMethod to see if it finds it, but it only finds it for the base class.
You should see the following results:
function () { this.output += "baseClassMethod"; }
undefined
undefined
undefined
Is it possible that the cause is that the call to the super constructor is messing with the 'this' context?
function extend(baseClass, subClass) {
var originalPrototype = subClass.prototype;
subClass.prototype = Object.create(baseClass.prototype);
for (var key in originalPrototype) {
subClass.prototype[key] = originalPrototype[key];
}
subClass.prototype.constructor = subClass;
Object.defineProperty(subClass.prototype, 'constructor', {
enumerable: false,
value: subClass
});
};
var baseClass = function() {
this.output = "Base: ";
this.toggleWizardHandlers = [];
this.baseClassMethod = function() {
this.output += "baseClassMethod";
};
};
baseClass.prototype.on = function(eventName, handler) {
switch (eventName.toLowerCase()) {
case "togglewizards":
return this.toggleWizardHandlers.push(handler);
break;
}
};
baseClass.prototype.toggleWizards = function(newWizard, newStepIndex) {
var handler, i, len, ref;
ref = this.toggleWizardHandlers;
for (var i = 0; i < ref.length; i++) {
handler = ref[i];
setTimeout(handler, 0, newWizard, newStepIndex);
}
};
var subClass = function() {
baseClass(this);
};
extend(baseClass, subClass);
var subSubClass = function() {
subClass(this);
};
extend(subClass, subSubClass);
var subSubSubClass = function() {
subSubClass(this);
};
extend(subSubClass, subSubSubClass);
var manager = function(settings) {
this.log = function(message) {
$("#log").html($("#log").html() + "<br />" + message);
};
this.clearLog = function() {
$("#log").html("");
};
this.testBaseClass = new baseClass();
this.testSubClass = new subClass();
this.testSubSubClass = new subSubClass();
this.testSubSubSubClass = new subSubSubClass();
//test.on("toggleWizards", function(param) { that.log(param); });
};
$(function() {
var manage = new manager("");
$("#btn").click(function() {
manage.log("start test");
manage.clearLog();
try {
manage.log(manage.testBaseClass.baseClassMethod);
} catch (e) {
manage.log(e);
}
try {
manage.log(manage.testSubClass.baseClassMethod);
} catch (e) {
manage.log(e);
}
try {
manage.log(manage.testSubSubClass.baseClassMethod);
} catch (e) {
manage.log(e);
}
try {
manage.log(manage.testSubSubSubClass.baseClassMethod);
} catch (e) {
manage.log(e);
}
});
});
Your prototype inheritance is working, you can try to access
on
ortoggleWizards
on all your instances.Your super calls in the constructors lack a crucial part though:
.call
. Without it, you are passingthis
for the first parameter, not as thethis
argument. Your base class is not able to initialise any properties on the subclass instance without this:When you call the super constructor, you need to use
apply
, not call it as a simple function.Otherwise your sub-classes new
this
object is passed as the first argument to the super constructor andthis
will refer to the global object (or null in strict mode).A small thing, it common to Capitalise constructor functions so that its clear that they should be called with
new
and not as regular functions.