3

所以我有以下内容:

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为一个对象时,它似乎为每个 new 存储相同的对象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/

谁能解释发生了什么/问题是什么。

4

2 回答 2

6

当你做了

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属性不驻留在对象c1c2. 当您说“给我c1.b”时,js 引擎会执行以下操作:

  1. b房产c1吗?不,没有。
  2. 让我们看一下原型c1(实际的原型,对象从什么获得方法和属性 - 在这种情况下,C.prototype
  3. 哦,是的,它有一个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对象上设置一个属性。
  • 在后一个示例中,您在c1s 原型上的对象上设置了一个属性,这会在所有其他对象上对其进行变异C
于 2013-06-10T07:30:07.080 回答
3

据我所知,这是发生的事情:

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;

当您编写时c1.b = 10,JavaSript 只会添加或更改b对象的本地属性c1。它并不关心原型是否已经具有b在这种情况下完全不受影响的属性。所以:

console.log(c1.b); // 10  --> local property in c1
console.log(c2.b); // 0   --> prototype property

在您的第二个示例中,您正在做一些不同的事情。您不是将属性分配给c1,而是在操纵它的原型,从而一起影响所有实例:

c1.b.a = 10;

c1没有属性b,因此它将从原型对象中获取并添加或更改 ITS 属性a。现在既没有c1c2没有获得本地属性,因此都指的是更改后的原型:

console.log(c1.b.a); // 10  --> points to the prototype
console.log(c2.b.a); // 10 --> points to the prototype

可能的解决方案

c1.b = new A();
c1.b.a = 10
于 2013-06-10T07:50:29.720 回答