【问题标题】:Non-enumerable properties appear in for...in loop in Chrome不可枚举的属性出现在 Chrome 的 for...in 循环中
【发布时间】:2012-08-27 17:18:10
【问题描述】:

for-in 循环将遍历对象的所有可枚举属性,甚至包括原型链中的属性。函数hasOwnProperty 可以过滤掉原型链中的那些可枚举属性。最后,函数propertyIsEnumerable可以区分对象的可枚举属性。

因此,以下脚本不应打印任何内容

for(a in window)
    if(window.hasOwnProperty(a) && !window.propertyIsEnumerable(a))
        console.log(a);

然而,在 Chrome 上,上面会打印 很多 属性名称。

为什么for-in 循环和propertyIsEnumerable 在可枚举方面相互矛盾?

【问题讨论】:

  • 在 Firefox 14 (fiddle) 上为我打印的零属性。
  • 请记住,windowhost 变量,不必完全遵循规范。
  • 是的,这很奇怪。 window.propertyIsEnumerable('Int8Array') 是假的,但 Object.getOwnPropertyDescriptor(window, 'Int8Array').enumerable 是真的。根据规格,它们应该是相等的。
  • 主机对象的东西是allowed,但是:“主机对象可以支持这些内部属性以及任何依赖于实现的行为”——即[[GetOwnProperty]],它是包含enumerable的描述符。
  • 例如:"主机对象可以以任何方式实现这些内部方法,除非另有说明;例如,一种可能性是 [[Get]] 和 [[Put]] 用于特定的宿主对象确实获取和存储属性值,但 [[HasProperty]] 总是生成 false。" es5.github.com/#x8.6.2。我不是说这里就是这种情况,它可能确实是一个错误,但必须牢记。

标签: javascript google-chrome


【解决方案1】:

可悲的事实是 JavaScript 引擎并不相同。虽然符合 ES5 的引擎会尽职尽责地尊重其属性的可枚举性,但 window 是一个宿主对象,正如上面 pimvdb 和 Felix 所指出的,不受 ES5 规则的约束。

您可以在window.constructor 中看到更多关于window 对象实际上是什么的证据,这将表明它是由

function Window() { [native code] }

因此,我们无法确定为什么某些属性是可枚举的(根据 Chrome),而其他属性不是来自 JavaScript 运行时。

但是,您仍然可以通过查看 Object.keys(window) 来查看 Chrome 不一致的 window 可枚举属性的完整状态,根据 its MDN article,“返回在给定对象上找到的所有自己的可枚举属性的数组。”

这样做仍然会返回一个包含 30 多个属性的数组。把它归咎于 Chrome 的陌生感!

编辑:通过一些进一步的测试,我找到了让 Chrome 理解 window 的可枚举属性的正确方法

Object.keys(window).filter(function(prop) {
  return window.hasOwnProperty(prop) && !window.propertyIsEnumerable(prop);
});

在 Chrome 中,for...in 枚举的候选属性列表似乎不是Object.keys 返回的内容,但实际上更接近于列出可枚举和不可枚举属性的Object.getOwnPropertyNames。然而,即使这样也不一致。在我的测试中,window.hasOwnProperty(prop) && !window.propertyIsEnumerable(prop) 的属性列表分别为 for...inObject.getOwnPropertyNames 的 423 和 454。

【讨论】:

  • 更奇怪的是我只看到Object.keys 的8 个属性。也许它应该被视为一个错误:)
  • 当涉及到主机属性的可枚举性时,更奇怪的是 Chrome 上的 for...in 的不一致行为。我发现另一个结果不一致的测试。
  • 摆弄它,我发现Chrome在使用Object.keys时实际上似乎尊重hasOwnProperty。也就是说,return !window.propertyIsEnumerable(prop); 就足够了。不过,这当然不是必需的。
【解决方案2】:

Chrome 很奇怪:

for(a in window)
    if(window.hasOwnProperty(a) && window.propertyIsEnumerable(a))
        console.log(a);

与 chrome 中的 450 个属性相比,它提供了大约 30 个属性。

【讨论】:

  • 你根本不需要hasOwnProperty - 只有自己的属性会被测试为可枚举
猜你喜欢
  • 2012-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 2010-11-09
相关资源
最近更新 更多