Chrome Opera 中 for-in 语句遍历出对象属性的顺序与定义的不同
问题描述
Chrome & Opera 中使用 for-in 语句遍历对象的属性时,遍历出的属性顺序与对象定义时不同。所以在使用 for-in 来处理属性顺序依赖的问题时常常会出错。
问题分析
Chrome Opera 中使用 for-in 语句遍历对象属性时会遵循一个规律,它们会先提取所有 key 的 parseFloat 值为非负整数的属性, 然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。
示例:
<script type="text/javascript"> window.onload = function(){ var obj = { a: 'A', z: 'Z', b: 'B', 12: 12, 7: 7, 0: 0, "-2": -2, "age": 15, "-3.5": -3.5, 7.7: 7.7, _: "___", online: true, 3: 3, "23": "23", "44": 44 }, info = document.getElementById("info"), key; for(key in obj){ info.innerHTML += key + " : " + obj[key] + "<br/>"; } } </script> <div id="info"></div>
以上代码测试了对象属性 key 为正负整数及小数、字符串和符号的情况下 for-in 语句遍历的顺序。执行代码,各浏览器中表现如下:
Chrome & Opera
0 : 0 3 : 3 7 : 7 12 : 12 23 : 23 44 : 44 a : A z : Z b : B -2 : -2 age : 15 -3.5 : -3.5 7.7 : 7.7 _ : ___ online : true
IE6,7,8 & Firefox & Safari
a : A z : Z b : B 12 : 12 7 : 7 0 : 0 -2 : -2 age : 15 -3.5 : -3.5 7.7 : 7.7 _ : ___ online : true 3 : 3 23 : 23 44 : 44
PS: 经测试该问题与文档模式、属性 value 的数据类型以及对象是否是直接量创建的无关。
可见,Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。
解决方案
for-in 语句无法保证遍历顺序,应尽量避免编写依赖对象属性顺序的代码。如果想顺序遍历一组数据,请使用数组并使用 for 语句遍历。 如果想按照定义的次序遍历对象属性,请参考本文针对各浏览器编写特殊代码。
附录:
ECMA标准参考
ECMA-262(ECMAScript)第三版:for-in 语句的属性遍历的顺序是由对象定义时属性的书写顺序决定的。请参考 ECMA-262 3rd Edition 中 12.6.4 The for-in Statement。
在现有最新的 ECMA-262(ECMAScript)第五版规范中,对 for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的。请参考 ECMA-262 5rd Edition 中 12.6.4 The for-in Statement。
评论
哈秀时尚 (未验证)
星期一, 08/12/2013 - 11:41
永久连接
谢谢博主
谢谢博主
添加新评论