所以我有以下内容:
function A () { this.a = 0; }
function B () { this.b = 0; }
function C () {}
C.prototype = new B();
var c1 = new C();
var c2 = new C();
c1.b = 10;
console.log(c1.b); // 10
console.log(c2.b); // 0
http://jsfiddle.net/Mars6/2/
当我将 B.b
更改为一个对象时,它似乎为每个新的 C
存储相同的对象:
function A () { this.a = 0; }
function B () { this.b = new A(); }
function C () {}
C.prototype = new B();
var c1 = new C();
var c2 = new C();
c1.b.a = 10;
console.log(c1.b.a); // 10
console.log(c2.b.a); // 10 - I want this to be 0
http://jsfiddle.net/Mars6/1/
任何人都可以解释发生了什么/问题是什么。
当你做的时候
C.prototype = new B();
您没有说“每当您需要原型(prototype)时,就做new B
”。你说的是“将原型(prototype)分配给 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 引擎会做这样的事情:
c1
上是否有b
属性?不,没有。
- 让我们看一下
c1
的原型(prototype)(实际原型(prototype),对象从中获取其方法和属性的对象 - 在本例中为C.prototype
)
- 哦,是的,它有一个
b
属性。归还它。
在实际的 js 中,这是 ( spec ):
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
的原型(prototype)上为一个对象设置了一个属性,该属性在所有其他 C
对象上发生了变化。