在 "for (… in …)" 循环中的元素顺序
在这段代码中,通过使用for-in循环遍历一个对象的属性,并将属性名和属性值拼接成字符串,最后打印出来。然后对这个对象进行了一些操作(修改、删除、重新添加),并再次进行了遍历和打印。代码运行在不同的浏览器中,包括Safari 5、Firefox 14、Chrome 21、Opera 12、Node 0.6和IE9。
问题出现在不同浏览器对于遍历对象属性的顺序上。根据规范,这些属性是无序的,但是不同的浏览器对于遍历的顺序处理不一致。比如在Safari 5和Firefox 14中,遍历的顺序是按照属性的插入顺序;而在Chrome 21、Opera 12、Node 0.6和Firefox 27中,遍历的顺序是按照属性的值的类型排序,整数属性在前,字符串属性在后;而在IE9中,遍历的顺序是按照属性的插入顺序,但是属性名没有被正确引用。
解决这个问题的方法是不要依赖于属性的顺序。因为规范中对于遍历顺序没有做具体要求,不同的引擎实现也有所不同。如果需要有序的遍历,可以将属性名保存在一个数组中,并按照需要进行排序。
这段代码中出现的问题是不同浏览器对于遍历对象属性的顺序处理不一致,解决方法是不要依赖于属性的顺序。
在"for (…in …)"循环中元素的顺序问题
在John Resig的文章中,他提到目前所有的主流浏览器都会按照属性定义的顺序循环遍历对象的属性。但是Chrome浏览器在某些情况下会有不同的行为。这个行为在ECMAScript规范中被明确规定为未定义,具体实现是由浏览器厂商决定的。
除了Chrome和Opera浏览器外,其他浏览器都会按照属性定义的顺序进行循环遍历。在Chrome和Opera浏览器中,属性会按照顺序先于非数字属性被提取出来。这与它们如何实现数组有关。对于Object.keys方法,其遍历顺序也是相同的。
下面的示例将清楚地说明情况:
var obj = { "first":"first", "2":"2", "34":"34", "1":"1", "second":"second" }; for (var i in obj) { console.log(i); }; // 遍历顺序: // "1" // "2" // "34" // "first" // "second"
需要注意的是,这个顺序可能随时改变,不能依赖于当前的顺序。
简而言之,如果顺序对你很重要,应该使用数组来存储数据。
在ES2015中,这个问题的答案是错误的。根据最新的消息,对于某些方法(如EnumerateObjectProperties和EnumerableOwnPropertyNames),属性的顺序是依赖于具体实现的。而对于Map对象来说,它们的迭代顺序是按照插入顺序的。而Object.keys方法的顺序仍然是依赖于具体实现的。
无论是在JSON中还是在JavaScript中,属性的顺序都是不确定的。在实际开发中,如果顺序对你很重要,应该使用数组来存储数据。