为什么foo.hasOwnProperty('__proto__')等于false?

9
var foo = {
  bar : 5
}

为什么foo.hasOwnProperty('__proto__')的结果是false
这不可能来自于原型链中更高层的任何对象,因为它是特定于此对象的。
编辑:
有些答案说它在Object.prototype上。
但我不明白这有什么道理。我的问题不在于它在哪里,而在于为什么它不在应该在的地方。
例如:
var a = new Foo();
var b = new Bar();
// Foo inherits from Bar

那么 a.__proto__b.__proto__ 不应该相等吗?

因为它们都读取自 Object.prototype


3
Object.prototype.__proto__有一个getter函数,当在不同的对象上调用时会返回不同的结果。例如,如果您运行Object.defineProperty(Object.prototype, 'self', {get: function(){return this}}),您可以在不同的对象上调用.self并获得不同的结果。 - Oriol
1个回答

7
事实上,__proto__是从Object.prototype继承而来的:
foo.hasOwnProperty('__proto__')              // false
Object.prototype.hasOwnProperty('__proto__') // true

根据MDN文章

__proto__属性并没有什么特别之处。它只是一个访问器属性——一个由getter函数和setter函数组成的属性——在Object.prototype上。

正如你所说的那样,直观地看,由于__proto__与每个对象密切相关,它应该是一个自有属性。
但事实并非如此。相反,Object.prototype.__proto__具有一个getter函数,当在不同的对象上调用时返回不同的值。
如果运行以下代码,则可以获得类似的结果:
Object.defineProperty(
    Object.prototype,
    'self',
    {get: function(){return this}}
)

现在,您可以在不同的对象上调用.self,并得到不同的结果。
同时注意,这种行为并不是__proto__的专属行为。例如,HTML元素的id属性也不是自有属性:
var el = document.createElement('div');
el.id = 'foo';
el.hasOwnProperty('id');                // false
Element.prototype.hasOwnProperty('id'); // true
(Webkit 浏览器不遵循规范,el.hasOwnProperty('id')true

所以...你的意思是__proto__不是对象实例的成员,而是Object.prototype的成员,它获取/设置当前实例的超级秘密特殊[[Prototype]]属性?因此,当您请求__proto__设置/获取时,它需要遍历整个原型链到根部才能获取getter/setter,然后才更改this的实际this.[[Prototype]]?这很糟糕。难怪他们建议使用Object.getPrototypeOf--您可以跳过动态分派到根部,并在常数时间内获取getter。 - Dmytro
@Dmitry,我在哪里可以找到Object.getPrototypeOf运行时间是恒定的信息? - rosshjb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接