__proto__似乎在null赋值后不起作用 - bug或功能?

时间:2014-05-07 14:57:31

标签: javascript

我观察到有关__proto__的行为对我来说似乎很奇怪:将__proto__更改为各种对象时,其行为符合预期,但一旦设置为null,就会再次将其更改为另一个对象似乎没有效果。

这是实施中的错误还是所需的行为?如果这是理想的行为,有人可以解释为什么?

一个示例JavaScript代码(所有测试都通过,直到最后一行):

p = {
  sum: function() {
    return this.x + this.y;
  }
};

o = {
  x: 1,
  y: 2
};

o.sum(); // As expected: TypeError: o.sum is not a function

// These all behave as expected:
o.__proto__ = p;
o.__proto__; // [object Object]
o.__proto__.sum; // [object Function]
o.sum(); // returns 3 :-)

// These all behave as expected:
o.__proto__ = {};
o.__proto__; // [object Object]
o.sum(); // TypeError: o.sum is not a function

// These all behave as expected:
o.__proto__ = p;
o.__proto__; // [object Object]
o.__proto__.sum; // [object Function]
o.sum(); // returns 3 :-)

// Still behaves more or less as expected:
o.__proto__ = null;
o.__proto__; // undefined (why undefined and not null?)
o.sum(); // TypeError: o.sum is not a function

// Seems fine, until the last line:
o.__proto__ = p;
o.__proto__; // [object Object]
o.__proto__.sum; // [object Function]
o.sum(); // Expected 3, but... TypeError: o.sum is not a function

我正在使用Firefox 28.0;不知道其他浏览器的反应。

1 个答案:

答案 0 :(得分:3)

问题是Firefox中的__proto__是使用Object.prototype函数实现的getter/setter上的实际属性。因此,当您将__proto__ o设置为null时,您会清除整个原型链,其中包含__proto__属性。

现在,当您分配到__proto__时,您只是将一个新的,普通的属性直接分配给o对象。


因此,为了获得__proto__的功能,您需要转到Object.prototype,并借用.set属性的__proto__方法,然后使用.call允许它在o对象上运行。

Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set.call(o, p);

因此,使用set调用Object.prototype.__proto__的{​​{1}}函数,以便.call成为o的{​​{1}}值,{ {1}}是要设置的值。这将使thisset进行操作,就像它是p的属性一样,允许它设置内部__proto__属性。


请注意,这仅在Firefox中测试。