两段小代码
第一段:
function Outer() {
this.a = 1;
}
function Inner() {
}
var outer = new Outer();
Inner.prototype = outer;
var inner = new Inner();
inner.a += 1;
console.log(inner.a, outer.a);
第二段:
function Outer() {
this.data = {
a: 1
};
}
function Inner() {
}
var outer = new Outer();
Inner.prototype = outer;
var inner = new Inner();
inner.data.a += 1;
console.log(inner.data.a, outer.data.a);
请问下为什么两段代码运行结果不一样呢?在第二段代码中,在inner中修改变量为何会影响到outer?
樓上都沒說到點上。
簡而言之,
結果等價於
並沒有對 inner 進行任何賦值操作,只是對 inner.data 進行了 GetValue。
而
inner.a
在不同上下文當中,含義有差異,主要體現在並沒有原型鏈尋址的過程。
詳細原因見下文。
c.d += b
是c.d = c.d + b
的縮寫,其中c.d
的位置必須是一個 LeftHandSideExpression。然而
c.d + b
中的c.d
和c.d = ...
中的c.d
是不同的,比如這裏c.d
是一個 PropertyReferance,c.d + b
會對c.d
進行 GetValue,從而遍歷c
的原型鏈尋找 屬性名爲"d"
的值而
c.d = ...
則會對c
的屬性"d"
賦值,而c
又不存在屬性d
,因此創建了新屬性,名爲d
。至於
c.d.e
當中的c.d
,則始終會被 GetValue,即便是c.d.e = ...
也仍舊是訪問了原型鏈上的c.d
。簡而言之這個問題的核心在於屬性尋址的機制:
而
加粗的操作就是導致這一區別的關鍵,使得
c.d.e
中的c.d
在任何上下文中都有相同的含義,而單純的c.d
在c.d + b
和c.d = ...
中有了區別。具體區別如下:
而 PutValue 中:
可見賦值的時候並不會像 GetValue 時那樣進行原型鏈尋址,而是直接修改了外層對象。