3
function Entity() {
    this.a = {a: 4};
    this.b = 5;
}

function Thing() {}
Thing.prototype = new Entity;

var thing1 = new Thing;
thing1.a.a = 3;
thing1.b = 4;
var thing2 = new Thing;
console.log(thing2.a.a); // prints 3 instead of 4. I would like 4.
console.log(thing2.b) // prints 5 as wanted

我在 javascript 中设置原型继承时遇到了困难。理想情况下,我希望 thing1 和 thing2 都有自己的“新实体原型”的干净副本。

usingthis.__proto__是我想避免的事情

[编辑]

我对它的工作原理有一个粗略的了解。

设置 thing1.b 会设置 Thing 实例的 b 属性。它不会触及原型链中定义的 Entity.b。

无法在 Thing 实例上设置 thing1.aa,因为它会引发“无法在未定义时设置”错误。那时它会沿着原型链查找 Entity.a,它已定义并将 Entity.aa 设置为新值。

[进一步编辑]

正如@IvoWetzel 所说,设置 thing1.b 不会触及原型链,因为设置属性不会。设置 thing1.aa 有两个步骤。thing1.a 上的getter,它触及原型链,后跟 .a 的 setter

4

3 回答 3

6

您可以做的一件事是在内部应用Entity构造函数的逻辑Thing,例如:

function Entity() {
    this.a = {a: 4};
    this.b = 5;
}
Entity.prototype.c = 6;

function Thing() {
  Entity.apply(this, arguments); // ejecutes the assignments made in Entity
}
Thing.prototype = new Entity;

var a = new Thing;
a.a.a = 3;

var b = new Thing;
console.log(a.a.a); // 3
console.log(b.a.a); // 4

console.log(a.b);   // 5
console.log(b.b);   // 5

console.log(a.c);   // 6
console.log(b.c);   // 6
于 2010-11-24T00:10:41.757 回答
2

虽然 CMS 已经发布了解决方案,但为什么thing2.b返回 5 以及为什么thing2.a.a解析到对象?

var thing1 = new Thing;

// thing1 has no a, but the prototype has so a.a is essentially the a of Entity
thing1.a.a = 3;

// Sets b on thing1, setting does not go up the prototype chain(!)
thing1.b = 4;  

// that's what thing1 looks like
Thing {proto: Entity { 
                      a: { <--- gets resolved 
                          a: 3 <-- gets set
                      }, 
                      b: 5
              },
              b: 4 <-- gets set directly
      }


var thing2 = new Thing;

// thing2.a does not exist, so we look up the prototype and find a on Entity
console.log(thing2.a.a); 

// thing2.b also does not exists, so once again we look up the prototype to find b on Entity
console.log(thing2.b);

// that's what thing2 looks like
Thing {proto: Entity {
                      a: {
                          a: 3 <- gets resolved
                      },
                      b: 5 <- gets resolved
              }
      }

所有的麻烦都在于 JavaScript 沿着原型链向上查找属性。但是,当您设置属性时,它不会上链。

于 2010-11-24T00:21:26.600 回答
0

这是因为 JavaScript 对象总是被视为引用。

因此,当您this.a通过执行更改对象时,a.a.a = 3;您正在更改内存中的那个对象。的新实例Thing将引用内存中的同一个对象,因为Entity不是每次都调用构造函数Thing,并且this.a对象保持不变。

我会把this.a原型链放在外面,可能直接放在Thing构造函数里面。这将使得this.a每次Thing实例化时都会在内存中创建一个新版本。

于 2010-11-24T00:13:25.050 回答