当你做了
C.prototype = new B();
你没有说“只要你需要原型,就去做new B
”。您所说的是“将原型分配给new B()
(这应该不足为奇)。您得到的是:
C.prototype.b.a === 0
每当您这样做new C
时,您都不会重复C.prototype
-您只是链接到它,链接到同一个B
对象:
C.prototype = new B()
^ ^
| |
c1 c2
c1.b === c2.b; //true
如您所知,可以随心所欲地更改对象。因此,当您这样做时c1.b.a = 4
,您将进入底层对象并弄乱它。
编辑:第一个示例之所以有效,是因为属性解析的工作方式。该b
属性不驻留在对象c1
或c2
. 当您说“给我c1.b
”时,js 引擎会执行以下操作:
- 有
b
房产c1
吗?不,没有。
- 让我们看一下原型
c1
(实际的原型,对象从什么获得方法和属性 - 在这种情况下,C.prototype
)
- 哦,是的,它有一个
b
属性。把它返还。
在实际的 js 中,这是(规范):
function GetProperty (name, obj) {
while (obj !== null) {
if (obj.hasOwnProperty(name)) {
return obj[name];
}
obj = Object.getPrototypeOf(obj);
}
return undefined;
}
所以,如果它b
是一个对象,那么你就持有一个对象。更改它会像普通对象一样更改它(请注意,您没有c1.b
直接分配给它 - 您会明白我的意思)。用箭头解释:
C.prototype.b = 0
^ ^
| |
c1.b c2.b
这很重要,所以我要再次强调:当你抓住 时c1.b
,你得到一个对象,它像任何其他对象一样被操纵。为它分配属性就像任何其他普通对象一样,并对其进行变异……嗯,对其进行变异。
现在,在前一种情况 ( c1.b = 10
) 中,您实际上是在分配一个属性。c1
这意味着您正在对象本身上创建键/值对。所以,第一步,我们看看是否c1
有一个属性b
——它有。用更多箭头解释:
C.prototype.b = 0
^
|
c1.b=10 c2.b
改变后一个例子,我们可以观察到同样的效果:
//changing
c1.b.a = 10;
//to
c1.b = 4;
c2.b !== 4 && c2.b.a === 0; //true
回顾一下:
- 在前一个示例中,您只需在
c1
对象上设置一个属性。
- 在后一个示例中,您在
c1
s 原型上的对象上设置了一个属性,这会在所有其他对象上对其进行变异C
。