2012-08-24 84 views
2

我對原型繼承的概念比較陌生,所以也許這是原型繼承應該如何工作,或者這只是javascript,但它似乎像原型繼承只是很好的主要類型。例如我有以下代碼:原型繼承中的奇怪行爲

var leg = { 
    type: null 
}; 

var Animal = { 
    traits: {}, 
    leg: Object.create(leg) 
}; 

var lion = Object.create(Animal); 
lion.traits.legs = 4; 
lion.leg.type = 'left'; 

var bird = Object.create(Animal); 
bird.traits.legs = 2; 
bird.leg.type = 'right'; 

alert(lion.traits.legs) // shows 2??? 
alert(lion.leg.type) // shows right??? 

最後兩行顯示我的困惑。這真的是原型繼承應該如何工作,或者這只是如何實現它的JavaScript?

如果這確實是原型繼承應該如何工作,那麼我真的不明白這種類型的繼承會是多麼有用。如果我只能擁有原始類型,那麼在創建複雜對象時似乎非常有限,因爲有很多情況下我有一個對象存儲另一個對象的實例。

+3

'traits'和'leg'對象被所有實例共享。只嚮應該共享的原型添加屬性,所有*實例特有的*屬於構造函數。 –

回答

2

不要繼承非原始的狀態。繼承方法。使每個對象都有自己的狀態。如果所有的對象都共享相同的狀態,那麼狀態就是使對象唯一的東西,沒有意義。

var Animal = { 
    method1: function() {}, 
    method2: function() {} 
}; 

var lion = Object.create(Animal, { 
    traits: { 
     value: {} 
    }, 
    leg: { 
     value: { 
      type: null 
     } 
    } 
}); 

var bird = Object.create(Animal, { 
    traits: { 
     value: {} 
    }, 
    leg: { 
     value: { 
      type: null 
     } 
    } 
}); 

順便說一句,有做幾乎同樣的事情更詳細和更好的支持的語法:

function Animal(traits, leg) { 
    this.traits = traits; 
    this.leg = leg; 
} 

var method = Animal.prototype; 

method.method1 = function() { 

}; 

method.method2 = function() { 

}; 


var lion = new Animal({}, {type: null}), 
    bird = new Animal({}, {type: null}); 
0

,這是它是如何工作的。屬性traitsleg是在實例之間共享的可變對象。原型繼承的想法是,除非明確地覆蓋它,否則從原型繼承所有狀態。您不要覆蓋字段traitleg,因此它們與原型共享。

這不同於基於類的繼承,其中狀態永遠不會被繼承,您必須初始化構造函數中的所有狀態。

可以有複雜的對象,但是如果每個實例都需要有它自己的新對象字段實例,你必須在創建實例後創建它們,就像在構造函數中一樣。

原型繼承是非常有用的(相對於基於類的繼承),因爲:

  1. 您可以節省大量的內存,因爲你只分配「槽」爲這是從樣機不同領域。在基於類的對象中,即使永遠不會從默認值更改,也必須爲所有字段分配空間。

  2. 很容易繼承更改。例如。例如,如果你在UI框架中有一個「窗口」原型,並且有很多具體窗口從這個原型繼承,你可以改變原型的顏色,並且它會自動繼承到所有沒有明確覆蓋它的實例。