Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

不可枚举属性被枚举的BUG

  一般来说,不可枚举(non-enumerable)属性是不应该被枚举出来的。即使对象的原型中存在同名的可枚举属性,它被一个不可枚举属性遮住时也不应该被枚举出来。这在ES5的for-in章节中被定义(ES5 12.6.4),但是在v8和IE上的实现存在BUG。
  从v8的代码(src/handles.cc#GetKeysInFixedArrayFor)上来分析,它在执行for-in时是遍历对象和其原型链,把所有可枚举属性都取出(还做了缓存),然后合并这些属性。如果目的是取出对象的所有可枚举属性,那这么做当然没问题。但是for-in的行为不是仅此而已,它还考虑对象自身的属性对原型中属性的遮盖。所以不能只考虑可枚举属性的情况,还需要取出不可枚举熟属性,去排除原型中的属性。
  既然算法已经是如此,那么就存在这样的问题
<script>
var o=Object.create(
  {n:0}, //原型对象中存在可枚举的n属性
  {n:{enumerable:false}} //对象的自身属性中存在不可枚举的n属性
);
for(var i in o)alert(o[i]);
</script>
  显然这里的n属性是不应该被枚举出来的,因为对象自身的n属性遮住了原型的n属性。但是只有在Firefox(25)中这个代码才正常工作(什么也不输出),而Chrome(31)和IE(9-11)中都会弹出undefined。这表明IE很有可能也许使用了和v8中类似的处理方式来实现for-in。而且注意这里弹出的结果是undefined而不是0,也就是说,对象自身不可枚举的n属性被输出了。这是因为for-in这东西遍历的只是属性名,而取属性又是另一回事。即使属性是不可枚举的,只要存在就会在执行[[Get]]时被访问到,从而挡住原型中的同名属性。
  最后,这个问题应该由引擎自己来解决,开发者现在只要知道目前依然存在这个问题就足够了。
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^