for-in遍历对象属性会导致顺序错乱

问题描述:Chrome和Opera中使用for-in语句遍历对象的属性时,遍历出的属性顺序与对象定义时不同,轻微的可能会导致界面数据显示顺序不对,如果有逻辑依托于这个顺序的话,可能会出现异常。

for-in遍历对象属性会导致顺序错乱

标准参考

根据 ECMA-262(ECMAScript)第三版中描述,for-in 语句的属性遍历的顺序是由对象定义时属性的书写顺序决定的

关于 ECMA-262(ECMAScript)第三版中 for-in 语句的更多信息,请参考 ECMA-262 3rd Edition 中 12.6.4 The for-in Statement。

在现有最新的 ECMA-262(ECMAScript)第五版规范中,对 for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的

关于 ECMA-262(ECMAScript)第五版中 for-in 语句的更多信息,请参考 ECMA-262 5rd Edition 中 12.6.4 The for-in Statement。

新版本中的属性遍历顺序说明与早期版本不同,这将导致遵循 ECMA-262 第三版规范内容实现的 JavaScript 解析引擎在处理 for-in 语句时,与遵循第五版规范实现的解析引擎,对属性的遍历顺序存在不一致的问题。

问题分析

Chrome和Opera中使用for-in语句遍历对象属性时会遵循一个规律,它们会先提取所有 key 的 parseFloat 值为非负整数的属性,然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。

可见,Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。1

【注】:IE6 IE7 IE8 Firefox Safari 浏览器的 JavaScript 解析引擎完成时间早于 ECMA-262 第五版规范发布时间,他们均遵守第三版规范,这无可厚非。

感兴趣的童鞋可以在不同浏览器运行如下代码:

<script type="text/javascript"> window.onload = function(){ var obj = { city: "Beijing", 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>

解决方案

for-in 语句无法保证遍历顺序,应尽量避免编写依赖对象属性顺序的代码。如果想保证顺序遍历,请使用数组并使用 for 语句遍历。

相关阅读