getOwnPropertyNames忽略Firefox上的__proto__

getOwnPropertyNames ignores __proto__ on Firefox

本文关键字:proto 上的 Firefox 忽略 getOwnPropertyNames      更新时间:2023-09-26

__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函数时采取步骤:

  1. 如果Type(O)不是Object,则抛出TypeError异常
  2. 数组是通过表达式new Array ()创建新对象的结果,其中Array是标准内置具有该名称的构造函数
  3. n为0
  4. 对于O的每个命名的自己的属性P
    1. name为字符串值,该值是P的名称
    2. 使用参数ToString(n)调用数组的[[DefineOwnProperty]]内部方法,PropertyDescriptor{[[Value]]:name、[[Writable]]:true、[[Enumerable]]:true、[Configuration]]:true[/strong>}和false
    3. n增加1
  5. 返回数组

__proto__Object.prototype的已命名own属性(否则,hasOwnProperty将返回false,因为[[GetOwnProperty]]将返回undefined)。因此,它应该由getOwnPropertyNames列出,不是吗?

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

19.1.2.7-Object.getOwnPropertyNames(O)

调用getOwnPropertyNames函数时采取步骤:

  1. 返回GetOwnPropertyKeys(O,字符串)

19.1.2.8.1-运行时语义:GetOwnPropertyKeys(O,Type)

使用参数O调用抽象操作GetOwnPropertyKeysType,其中O是Object,Type为ECMAScript之一规范类型字符串或符号。采取以下步骤:

  1. obj为ToObject(O
  2. ReturnIfAbrupt(对象
  3. 对象。[OwnPropertyKeys]
  4. ReturnIfAbrupt(
  5. nameList成为一个新的空列表
  6. 按列表顺序对keysnextKey中的每个元素重复上述操作,
    1. 如果Type(nextKey)为Type,则
      1. nextKey附加为nameList的最后一个元素
  7. 返回CreateArrayFromList(nameList

9.1.12-[[OwnPropertyKeys]]()

O的[[OwnPropertyKeys]]内部方法被调用时采取以下步骤:

  1. 成为一个新的空列表
  2. 对于O的每个属性键P,它是一个整数索引,按数字索引升序排列
    1. 添加P作为的最后一个元素
  3. 对于O的每个自己的属性键P,它是字符串但不是整数索引,按属性创建顺序
    1. 添加P作为的最后一个元素
  4. 对于属于Symbol的O的每个属性键P,按属性创建顺序
    1. 添加P作为的最后一个元素
  5. 返回

[[OwnPropertyKeys]]应返回包含"__proto__"的列表,GetOwnPropertyKeys应返回具有"__proto__"的数组,因为其类型应为String。

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

所以,这是一个bug,还是这里应用了什么复杂的规范?

是的,这似乎是一个错误。从这个错误报告(观察到类似的奇怪情况):

我们在没有[[Prototype]],因为我们不想把它暴露在网络上。或者在至少这是当时的意图,尤其是因为没有其他浏览器以这种方式公开了Object.prototype上的属性是杀死__原__的机会。我仍然有一些希望__质子可以被杀死,我自己;其他人不同意。

他们需要为ES6修复此问题。