2011-10-11 24 views
0

基本上,我正在嘗試做的是已經討論過很多次。但是,大多數示例僅具有從ClassB繼承的ClassA。我的情況很瑣碎,但似乎並沒有在我發現的JavaScript主題中解決。繼承不止一次,保持每個實例的私有成員

ClassB擴展ClassA,它有一個成員。 ClassC和ClassD擴展了ClassB。但是,在ClassC的實例中設置唯一成員時,此成員也設置在ClassD的成員中。讓我們來看一個例子:

function ClassA(data) { 
     var This = this; 
     This._data = {}; 

     This._construct = function(data) { 
      if(undefined === data) { 
       This._data = {}; 
       return true; 
      } 

      This._data = data; 
     } 


     This._construct(data); 
    } 

    function ClassB() { 
    } 
    ClassB.prototype = new ClassA(); 
    ClassB.prototype.constructor = ClassB; 

    function ClassC() { // Extends ClassB 
    } 
    ClassC.prototype = new ClassB(); 
    ClassC.prototype.constructor = ClassC; 

    function ClassD() { // Extends ClassB 
    } 
    ClassD.prototype = new ClassB(); 
    ClassD.prototype.constructor = ClassD; 


    var objectC = new ClassC(); 
    var objectD = new ClassD(); 

    objectC._data['somevar'] = 'asdasdasd'; 
    console.log(objectC._data); // Object { somevar="asdasdasd"} 
    console.log(objectD._data); // Object { somevar="asdasdasd"} 

如果設置上線console.log(objectC._data);一個斷點,您可以在螢火蟲的觀察窗口,所有原型正確設置見。這很奇怪,因爲ClassC和ClassD的原型顯然是用new關鍵字創建的獨立實例,因此不應共享成員。有人可以解釋嗎?

_construct()函數可以從ClassA中移除,不起作用。 var This = this行可以被刪除,所有後續對This的引用可以更改爲this,但不起作用。

+0

問題解決。 對於那些真正想知道自己在做什麼的極客們來說,看看[這篇神奇的文章](http://blog.niftysnippets.org/2009/09/simple-efficient-supercalls-in.html)。 我使用jQuery,所以[this plugin](http://plugins.jquery.com/project/jClass)看起來是正確的解決方案。 – XedinUnknown

+0

好吧,[這個插件](http://plugins.jquery.com/project/jClass)是垃圾,充滿了錯誤,看起來像是被作者拋棄了。相反,檢查[這一個](https://github.com/kilhage/class.js) – XedinUnknown

回答

0

爲了讓這個模式有效,你需要在每個類中調用super。這是你如何可以。

//Simplifying the construction part a bit. 
function ClassA(data) { 
    this._data = data || {}; 
} 

function ClassB(data) { 
    ClassA.call(this, data); //call super class (ClassA) constructor 
    //here you can initialize any ClassB specific variables 
} 
ClassB.prototype = new ClassA(); 
ClassB.prototype.constructor = ClassB; 

function ClassC(data) { // Extends ClassB 
    ClassB.call(this, data); //call super class (ClassB) constructor 
    //here you can initialize any ClassC specific variables 
} 
ClassC.prototype = new ClassB(); 
ClassC.prototype.constructor = ClassC; 

function ClassD(data) { // Extends ClassB 
    ClassB.call(this, data); //call super class (ClassB) constructor 
    //here you can initialize any ClassD specific variables 
} 
ClassD.prototype = new ClassB(); 
ClassD.prototype.constructor = ClassD; 


var objectC = new ClassC(); 
var objectD = new ClassD(); 

objectC._data['somevar'] = 'asdasdasd'; 

console.log(objectC._data); // Object { somevar="asdasdasd"} 
console.log(objectD._data); // Object {} -- empty for objectD 

現在你可以看到_data不跨實例共享。

+0

'_data = {}'和'x ='testmember'' ..之間有什麼區別?我沒有看到任何區別。但是,作爲原始帖子評論發佈的文章詳細解釋了這一點。 – XedinUnknown

+0

@XedinUnknown我只是指出'x'不是跨實例共享,而是'_data'是共享的。不同之處在於'_data'是一個「對象」,'x'是一個「字符串」。再次,我不完全確定爲什麼會發生這種情況。順便說一句,你發佈的文章是好的。感謝那。 –

+0

在你的具體情況下,這是因爲在JavaScript中,原始類型是按值傳遞的,而對象是通過引用傳遞的。但是,因爲構建或多或少複雜的應用程序時,我們需要一致的可靠行爲,所以您的方法不是一種解決方案 - 僅僅因爲它不是一種方法。如果我需要一個對象,我不能只使用一個原語。 – XedinUnknown