__proto__
是Object.prototype
的属性:
Object.prototype.hasOwnProperty('__proto__'); // true
但是,getOwnPropertyNames在Firefox上将忽略它:
Object.getOwnPropertyNames(Object.prototype).indexOf('__proto__'); // -1
它适用于Chromium 43和IE 11。
AFAIK,根据ECMAScript 5规范,getOwnPropertyNames应该列出它:
15.2.3.4 - Object.getOwnPropertyNames ( O )
调用getOwnPropertyNames函数时,以下内容
采取的步骤:
如果Type(O)不是Object,则抛出TypeError异常。
令array为创建新对象的结果,就像通过表达式
new Array ()
一样,其中Array
是标准内置对象该名称的构造函数。
令n为0。
对于每个命名的自己的财产P of O
令name为String值,即P的名称。
使用参数ToString(n),PropertyDescriptor {[[Value]]调用数组的[[DefineOwnProperty]]内部方法。
名称,[[可写]]:是,[[可枚举]]:是,[[可配置]]:是}和否。
n递增1。
返回数组。
__proto__
是Object.prototype
的命名自有属性(否则,hasOwnProperty将返回false,因为[[GetOwnProperty]]将返回undefined)。因此,它应该由getOwnPropertyNames列出,不是吗?ECMAScript 6是否应该有所不同? ES6草案确实更改了一些内容:
19.1.2.7 - Object.getOwnPropertyNames ( O )
调用getOwnPropertyNames函数时,以下内容
采取的步骤:
返回GetOwnPropertyKeys(O,String)。
19.1.2.8.1 - Runtime Semantics: GetOwnPropertyKeys ( O, Type )
使用参数O调用抽象操作GetOwnPropertyKeys
和类型,其中O是对象,类型是ECMAScript之一
规范类型字符串或符号。采取以下步骤:
令obj为ToObject(O)。
ReturnIfAbrupt(obj)。
令键为obj。[OwnPropertyKeys]。
ReturnIfAbrupt(键)。
令nameList为新的空List。
对每个元素按List顺序重复键的nextKey,
如果Type(nextKey)是Type,则
追加nextKey作为nameList的最后一个元素。
返回CreateArrayFromList(nameList)。
9.1.12 - [[OwnPropertyKeys]] ( )
当O的[[OwnPropertyKeys]]内部方法称为
采取以下步骤:
令键为新的空List。
对于每个作为整数索引的O的property key P,以数字索引升序
将P添加为键的最后一个元素。
对于每个自己的property key P of O(按字符串创建,但不是整数索引),按属性创建顺序
将P添加为键的最后一个元素。
对于每个作为符号的O的property key P,按属性创建顺序
将P添加为键的最后一个元素。
返回键。
[[OwnPropertyKeys]]应该返回一个包含
"__proto__"
的列表,而GetOwnPropertyKeys应该返回一个带有"__proto__"
的数组,因为它的类型应该是String。即使是Symbol而不是String(这没有什么意义),getOwnPropertySymbols也应包含
__proto__
,但它会返回一个空数组。因此,这是一个错误还是规范的错综复杂?
最佳答案
是的,这似乎是一个错误。从this bug report(观察到类似的奇怪之处):
我们从对象的属性中过滤出__proto__,而没有
[[Prototype]],因为我们不想将其公开。或
至少那是当时的意图,尤其是因为没有其他
浏览器以这种方式公开了Object.prototype的属性,
是杀死__proto__的机会。我仍然有希望
我自己可以杀死__proto__;其他人不同意。
他们将需要针对ES6修复此问题。
关于javascript - getOwnPropertyNames在Firefox上忽略__proto__,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29104906/