Web 技术研究所

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

v8中shift操作带来的属性破坏

  上一篇文章中介绍的pop问题只是v8屏蔽了一个错误而已,并不对数据造成影响,不是什么大问题。但shift的问题可就严重,由于v8的一些优化机制,使得数组元素上设置的configuration可能失效,即使元素的[[Configurable]]为false也一样有可能被删除。
<script>
var a=[0,1,2,3,4,5,6,7,8];
Object.defineProperty(a,9,{value:9});
a.unshift(a.shift()); //IE和Firefox抛出异常
//Chrome正常输出每个数组元素,不会死循环
while(a.length)console.log(a.pop());
</script>

  这个代码在v8中不会出现死循环,也不会抛出异常。数组被很正常地一个个取出元素了,这反而不对劲!我们定义的[[Configurable]]为false的属性居然也被移除了!为什么?
  在v8中对一些需要移动元素的数组方法使用了一个叫SmartyMove的优化机制。它会考虑数组的稠密性,对于稀疏数组格外有效。它的实现方式是把结果需要得到的数据复制到一个临时数组上,最后再把临时数组的数据复制原数组对象。由于最后的步骤是直接的堆复制,不使用[[Delete]]内置方法逐个删除元素,所以这个操作不受[[Configurable]]的影响。而且仅复制了数据部分,导致原数组元素的configuration丢失。当我们再次用unshift放入元素时,就变成了添加一个普通的新元素,所以我们使用pop可以正常把数组遍历出来而不进入死循环。shift只是一个例子,问题出在SmartyMove上,所用使用了这个机制的方法都存在同样问题。
网名:
54.144.24.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^