Reputation: 8876
I'm playing around with inheritance in Javascript, trying to wrap my head around creating classes and child classes using Object.create. So far, so good, but I've hit a sticking point.
I have a base class with some public and private variables and functions. From that, I've created an "advanced" class with its own public and private variables and functions. Everything works as expected until working with the child class, and I try to access its own private variable from inside its own private function.
The call to A3.tellASecret()
at the very bottom is the start of the stack. It goes to this.tellASecret
inside AdvancedClass
(as expected). From there, I make the call to secretTellAdvSecret.call(this)
, using call
because I know I'll lose the scope if I don't. When I get inside secretTellAdvSecret
, the private variable avdPrivateVar
is undefined.
Before jumping to conclusions, I jumped into the inspector, and here's where it got a little weird for me. I can see that this
is still an AdvancedClass
, which is good, but of course doesn't explain anything, because I already know I was carrying the scope. When I looked at the closure, I see everything I expect: baseInput
& advInput
with the right values, and secretTellAdvSecret
is there, too... But there's no advPrivateVar
. I understand that's why it's undefined when I get to this point (duh), but I don't understand why it's not there. It was defined within the closure, so shouldn't it be available within the closure?
Any ideas on where I'm tripping up or missing something?
var BaseClass = function(baseInput){
console.log('> new BaseClass(%s)', Array.prototype.slice.call(arguments).toString());
var basePrivateVar = (baseInput)?('(private)' + baseInput):'baseSecret';
this.basePublicVar = (baseInput)?('(public)' + baseInput):'baseNotSecret';
function secretTellBaseSecret(){
console.log('> BaseClass::secretTellBaseSecret(%s)', Array.prototype.slice.call(arguments).toString());
return basePrivateVar;
}
this.tellSecret = function(){
console.log('> BaseClass::tellSecret(%s)', Array.prototype.slice.call(arguments).toString());
var x = secretTellBaseSecret();
return secretTellBaseSecret();
};
};
BaseClass.prototype = {
tellSecret: function(){
console.log('> BaseClass.prototype.tellSecret(%s)', Array.prototype.slice.call(arguments).toString());
return this.tellSecret();
}
};
var AdvancedClass = function(baseInput, advInput){
console.log('> new AdvancedClass(%s)', Array.prototype.slice.call(arguments).toString());
BaseClass.call(this, baseInput);
var advPrivateVar = (advInput)?('(private)' + advInput):'advSecret';
this.advPublicVar = (advInput)?('(public)' + advInput):'advNotSecret';
function secretTellAdvSecret(){
console.log('> AdvancedClass::secretTellAdvSecret(%s)', Array.prototype.slice.call(arguments).toString());
return avdPrivateVar;
};
this.tellASecret = function(){
console.log('> AdvancedClass::tellSecret(%s)', Array.prototype.slice.call(arguments).toString());
return secretTellAdvSecret.call(this);
};
};
AdvancedClass.prototype = Object.create(BaseClass.prototype, {
tellBaseSecret: {
value: function(){
console.log('> AdvancedClass.prototype.tellBaseSecret', Array.prototype.slice.call(arguments).toString());
return BaseClass.prototype.tellSecret.apply(this, arguments);
},
enumerable: true
}
});
AdvancedClass.prototype.constructor = AdvancedClass;
var A1 = new BaseClass("A1's secret");
console.log("A1's secret = " + A1.tellSecret());
var A2 = new BaseClass("A2's secret");
console.log("A2's secret = " + A2.tellSecret());
console.log("A1's secret = " + A1.tellSecret());
var A3 = new AdvancedClass("A3's base secret", "A3's advanced secret");
console.log("A3's base secret = " + A3.tellSecret());
console.log("A3's base secret = " + A3.tellBaseSecret());
console.log("A3's advanced secret = " + A3.tellASecret());
Upvotes: 0
Views: 86
Reputation: 2790
It looks like you have a typo in your code:
function secretTellAdvSecret(){
console.log('> AdvancedClass::secretTellAdvSecret(%s)', Array.prototype.slice.call(arguments).toString());
return avdPrivateVar; // typo
};
Change to this:
function secretTellAdvSecret(){
console.log('> AdvancedClass::secretTellAdvSecret(%s)', Array.prototype.slice.call(arguments).toString());
return advPrivateVar; // this line
};
Upvotes: 1