TheJim01
TheJim01

Reputation: 8876

Javascript inheritance, child class's own private variables

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

Answers (1)

krg
krg

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

Related Questions