__proto__似乎不能在null赋值后工作- bug或特性

__proto__ doesn't seem to work after a null assignment - bug or feature?

本文关键字:工作 bug 赋值 proto 不能 null      更新时间:2023-09-26

我观察到关于__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;不知道其他浏览器的反应

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

现在,当你给__proto__赋值时,你只是直接给o对象赋了一个新的、正常的、没有预期行为的属性。


所以为了获得__proto__的功能,你需要去Object.prototype,借用__proto__属性的.set方法,使用.call允许它对o对象进行操作。

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

因此,使用.call调用Object.prototype.__proto__set函数,使o成为setthis值,而p是正在设置的值。这将使__proto__o进行操作,就好像它是o的属性一样,允许它设置[[Prototype]]的内部属性。