[英]About the prototype object and it's role in Javascript inheritance
我剛剛開始搞亂Javascript繼承,並且不能讓我圍繞這個:
如果我運行此代碼:
function Foo(y) {
this.y = y;
}
Foo.prototype.x = 1;
var Bar1 = new Foo(2);
var Bar2 = new Foo(3);
我希望在內存中有以下“結構”: 我在圖中搞砸了,Bar2的屬性“y”顯然值為“3”
幸運的是,我可以通過運行此代碼來確認:
console.log("Prototype - x: ", Foo.prototype.x, " y: ", Foo.prototype.y);
console.log("Bar1 - x: ", Bar1.x, " y: ", Bar1.y);
console.log("Bar2 - x: ", Bar2.x, " y: ", Bar2.y);
打印:
Prototype - x: 1 y: undefined
Bar1 - x: 1 y: 2
Bar2 - x: 1 y: 3
糾正我,如果我錯了,但是當我嘗試訪問Bar1和Bar2對象中的屬性x時,因為那些對象不是localy有一個名為x的屬性,我從那里獲得該屬性原型鏈中的下一個對象; 即他們在“_ proto _”屬性中存儲的引用。
現在是我迷路的時候,因為如果我在那段代碼之后改變x的值,就像這樣:
Bar1.x = 10;
當我現在跑
console.log("Prototype - x: ", Foo.prototype.x, " y: ", Foo.prototype.y);
console.log("Bar1 - x: ", Bar1.x, " y: ", Bar1.y);
console.log("Bar2 - x: ", Bar2.x, " y: ", Bar2.y);
我得到的是
Prototype - x: 1 y: undefined
Bar1 - x: 10 y: 2
Bar2 - x: 1 y: 3
而不是我期望的:
Prototype - x: 10 y: undefined
Bar1 - x: 10 y: 2
Bar2 - x: 10 y: 3
那時我只能通過假設每個對象都在創建Foo.prototype對象的副本來解釋它,但如果我運行這個
console.log(Object.is(Foo.prototype, Bar1.__proto__), Object.is(Bar1.__proto__, Bar2.__proto__));
我true true
,所以Bar1,Bar2都在訪問同一個對象。
為什么Bar1然后顯示x的不同值,如果它們都是從同一個對象獲取它?
這一行:
Bar1.x = 10;
不會改變原型中x
的值。 相反,它為Bar1
創建一個新屬性( x
)並為其賦值10
。 因此, Bar1
不再從其原型繼承x
,因為它現在具有自己的屬性x
。
Bar2
仍然存在,這就是為什么它仍然匹配原型值。
這很簡單:
賦值始終在對象本身上創建或更新屬性。
賦值永遠不會影響原型鏈,即使屬性存在於鏈的某個位置(*)。
只讀取屬性遍歷原型鏈,停在實際具有該屬性的對象上。
如果您對技術問題感興趣,請查看規范中的PutValue
定義 。
(*):但是,如果屬性存在於原型鏈中,則可能會對分配產生影響。 如果屬性存在且只讀 (不可寫),則賦值不會創建新屬性。 例:
> var obj = Object.create(Object.create({}, {x: {value: 10}}));
undefined
> obj.x
10
> obj.x = 100;
100
> obj.x
10
你說得對如何Bar1
和Bar2
得到他們的價值觀x
。 但是當它分配時, Bar1.x = 10
。
嘗試訪問x
,它首先從對象本身開始,然后向下爬行鏈。 假設您嘗試訪問Bar1.z
查找看起來像這樣:
Bar1.z
Bar1.prototype.z
Bar1.__proto__.z
即Foo.prototype
Object.prototype.z
(因為所有對象都自然地從Object
繼承 z
,返回undefined
通過分配Bar1.x
,您可以有效地遮蔽Bar1.x
Bar1.__proto__.x
的值,因為它將首先出現在查找中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.