The reason it sort of seems to work with the commented out line is that myChildClass
in that commented-out line is the function; but in the line inside the myChildClass
constructor, this
is not the function, it's the instance created by the new
operator. The prototype
property on functions is the object that will be assigned by the new
operator to the new instances it creates, as their underlying prototype; there is no special meaning to the prototype
property on instances (it doesn't, for instance, refer to the instance's underlying prototype).
The correct way to do this is this:
// Parent constructor
function myMotherClass(value){
this.MyValue = value
}
// Child constructor
function myChildClass(value){
// Chain to parent constructor, passing any necessary args
myMotherClass.call(this, value);
// Other child stuff -- see note below
this.alert = function(){
alert(value);
};
}
// Set up inheritance by creating myChildClass's prototype
// property to be an object that is baked by myMotherClass's
// prototype object; do NOT *call* myMotherClass here, it's
// a common anti-pattern you'll see in a lot of examples
inherit(myMotherClass, myChildClass);
// Create an instance
var myClass = new myChildClass(2);
myClass.alert();
...where inherit
is:
function inherit(parent, child) {
var temp;
if (Object.create) {
child.prototype = Object.create(parent.prototype);
} else {
temp = function() { };
temp.prototype = parent.prototype;
child.prototype = new temp();
}
child.prototype.constructor = child;
}
Note that with the way you're defining alert
, this slightly strange behavior occurs:
var o = new myChildClass(42);
console.log(o.MyValue); // 42
o.alert(); // alerts "42"
o.MyValue = 67;
console.log(o.MyValue); // 67
o.alert(); // alerts "42" <== !!!
You can change how you define alert
so it uses MyValue
like this:
this.alert = function() {
alert(this.MyValue);
};
...provided you always call it through the instance. (More on my blog: Mythical methods)
But if you're going to do that, you can move it to the prototype -- put this after the inherit
call that sets up the chain:
myChildClass.prototype.alert = function(){
alert(this.MyValue);
};
Here's that all put together:
// Parent constructor
function myMotherClass(value){
this.MyValue = value
}
// Child constructor
function myChildClass(value){
// Chain to parent constructor, passing any necessary args
myMotherClass.call(this, value);
// Other child stuff...
}
// Set up inheritance by creating myChildClass's prototype
// property to be an object that is baked by myMotherClass's
// prototype object; do NOT *call* myMotherClass here
inherit(myMotherClass, myChildClass);
// Add stuff to myChildClass's prototype property
myChildClass.prototype.alert = function(){
alert(this.MyValue);
};
// Create an instance
var myClass = new myChildClass(2);
myClass.alert();
If you're interested in classical inheritance in JavaScript, I have a handy helper script, Lineage
, that makes the above simpler and adds a few useful features: http://code.google.com/p/lineagejs/