我观察到有关__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;不知道其他浏览器的反应。
答案 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}}是要设置的值。这将使this
对set
进行操作,就像它是p
的属性一样,允许它设置内部__proto__
属性。
请注意,这仅在Firefox中测试。