在使用for in语句获取对象属性时,我们会发现在部分浏览器中实际的输出顺序与定义的不一致。这是因为浏览器的JavaScript 解析引擎遵循的规范不一致的原因。
根据 ECMA-262(ECMAScript)第三版中描述,for-in 语句的属性遍历的顺序是由对象定义时属性的书写顺序决定的。而在现有最新的 ECMA-262(ECMAScript)第五版规范中,对 for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的。
新版本中的属性遍历顺序说明与早期版本不同,这将导致遵循 ECMA-262 第三版规范内容实现的 JavaScript 解析引擎在处理 for-in 语句时,与遵循第五版规范实现的解析引擎,对属性的遍历顺序存在不一致的问题。
遵循第五版规范的浏览器(Chrome Opera等)会先提取所有 key 的 parseFloat 值为非负整数的属性,然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。
由于对象的输出是无序的,但是数组却是有序的,所以如果想保证对象属性的遍历顺序,请使用数组来存储 key 并使用 for 语句遍历。
const 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
};
console.log(Object.keys(obj)); // ["0", "3", "7", "12", "23", "44", "city", "-2", "age", "-3.5", "7.7", "_", "online"]