getOwnPropertyNames 在 Firefox 上忽略 __proto__

getOwnPropertyNames ignores __proto__ on Firefox

__proto__Object.prototype 的 属性:

Object.prototype.hasOwnProperty('__proto__'); // true

但是,getOwnPropertyNames 在 Firefox 上会忽略它:

Object.getOwnPropertyNames(Object.prototype).indexOf('__proto__'); // -1

它适用于 Chromium 43 和 IE 11,很难。

据我所知,根据 ECMAScript 5 规范,getOwnPropertyNames 应该列出它:

15.2.3.4 - Object.getOwnPropertyNames ( O )

When the getOwnPropertyNames function is called, the following steps are taken:

  1. If Type(O) is not Object throw a TypeError exception.
  2. Let array be the result of creating a new object as if by the expression new Array () where Array is the standard built-in constructor with that name.
  3. Let n be 0.
  4. For each named own property P of O
    1. Let name be the String value that is the name of P.
    2. Call the [[DefineOwnProperty]] internal method of array with arguments ToString(n), the PropertyDescriptor {[[Value]]: name, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
    3. Increment n by 1.
  5. Return array.

__proto__Object.prototype 的命名自己的 属性(否则,hasOwnProperty would return false because [[GetOwnProperty]] 将 return 未定义)。因此,它应该被getOwnPropertyNames列出,不是吗?

在 ECMAScript 6 中应该有所不同吗? ES6 草案确实改变了一些事情:

19.1.2.7 - Object.getOwnPropertyNames ( O )

When the getOwnPropertyNames function is called, the following steps are taken:

  1. Return GetOwnPropertyKeys(O, String).

19.1.2.8.1 - Runtime Semantics: GetOwnPropertyKeys ( O, Type )

The abstract operation GetOwnPropertyKeys is called with arguments O and Type where O is an Object and Type is one of the ECMAScript specification types String or Symbol. The following steps are taken:

  1. Let obj be ToObject(O).
  2. ReturnIfAbrupt(obj).
  3. Let keys be obj.[OwnPropertyKeys].
  4. ReturnIfAbrupt(keys).
  5. Let nameList be a new empty List.
  6. Repeat for each element nextKey of keys in List order,
    1. If Type(nextKey) is Type, then
      1. Append nextKey as the last element of nameList.
  7. Return CreateArrayFromList(nameList).

9.1.12 - [[OwnPropertyKeys]] ( )

When the [[OwnPropertyKeys]] internal method of O is called the following steps are taken:

  1. Let keys be a new empty List.
  2. For each own property key P of O that is an integer index, in ascending numeric index order
    1. Add P as the last element of keys.
  3. For each own property key P of O that is a String but is not an integer index, in property creation order
    1. Add P as the last element of keys.
  4. For each own property key P of O that is a Symbol, in property creation order
    1. Add P as the last element of keys.
  5. Return keys.

[[OwnPropertyKeys]] 应该 return 一个包含 "__proto__" 的列表,而 GetOwnPropertyKeys 应该 return 一个包含 "__proto__" 的数组,因为它的类型应该是字符串。

即使它是 Symbol 而不是 String(这没有多大意义),getOwnPropertySymbols 也应该包含 __proto__,但它 return 是一个空数组。

因此,这是一个错误,还是规范的复杂之处适用于此?

是的,这似乎是一个错误。来自 this bug report(观察到类似的奇怪现象):

We filter __proto__ out of properties on objects without a [[Prototype]], because we don't want to expose it to the web. Or at least that was the intent at the time, especially since no other browser exposed the property on Object.prototype that way, and there was a chance at killing __proto__. I still have some hope that __proto__ can be killed, myself; others disagree.

他们需要为 ES6 解决这个问题。