2015-04-16 100 views
0

我在Javascript中玩弄繼承,嘗試圍繞使用Object.create創建類和子類的過程。到目前爲止,這麼好,但我遇到了一個棘手的問題。Javascript繼承,子類自己的私有變量

我有一個公共和私有變量和函數的基類。從那以後,我創建了一個具有自己的公共和私有變量和函數的「高級」類。一切都按預期工作,直到使用子類爲止,並且我嘗試從自己的私有函數中訪問自己的私有變量。

最底層A3.tellASecret()的調用是堆棧的開始。它在AdvancedClass之內去this.tellASecret(如預期)。從那裏,我打電話給secretTellAdvSecret.call(this),使用call,因爲我知道如果我不知道我會失去範圍。當我進入secretTellAdvSecret時,私有變量avdPrivateVar未定義。

在跳到結論之前,我跳進了檢查員,這裏對我來說有點奇怪。我可以看到,this仍然是一個AdvancedClass,這很好,但當然不能解釋任何事情,因爲我已經知道我攜帶的範圍。當我看到關閉時,我看到了我期望的一切:baseInput & advInput正確的值,並且secretTellAdvSecret也在那裏......但是沒有advPrivateVar。我明白這就是爲什麼當我到達這個點時它是不確定的,但我不明白爲什麼它不在那裏。它是在關閉中定義的,所以不應該在關閉中提供?

關於我絆倒或缺少什麼的任何想法?

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()); 
+1

看起來像一個錯字,你想引用它作爲'avdPrivateVar '......注意第二個和第三個字母的順序。 – Hargobind

+1

avdPrivateVar只在您的代碼中出現一次,很確定它是錯誤的 – Patrick

回答

1

它看起來像你必須在你的代碼一個錯字:

function secretTellAdvSecret(){ 
    console.log('> AdvancedClass::secretTellAdvSecret(%s)', Array.prototype.slice.call(arguments).toString()); 
    return avdPrivateVar; // typo 
}; 

改成這樣:

function secretTellAdvSecret(){ 
    console.log('> AdvancedClass::secretTellAdvSecret(%s)', Array.prototype.slice.call(arguments).toString()); 
    return advPrivateVar; // this line 
};