在 "for (… in …)" 循环中的元素顺序

11 浏览
0 Comments

在 "for (… in …)" 循环中的元素顺序

在JavaScript中,“for...in”循环会按照它们声明的顺序循环遍历哈希表/元素吗?是否有浏览器不按顺序执行?我希望使用的对象将被声明一次并且永远不会被修改。

假设我有:

var myObject = { A: "Hello", B: "World" };

然后我在以下代码中进一步使用它们:

for (var item in myObject) alert(item + " : " + myObject[item]);

我可以期望在大多数好的浏览器中,'A : "Hello"'总是在'B : "World"'之前出现吗?

0
0 Comments

在《ECMAScript语言规范》的第12.6.4节(关于for .. in循环)中提到:

枚举属性的机制取决于具体实现。枚举的顺序由对象定义。

而在第4.3.3节中(关于"对象"的定义):

对象是一个无序的属性集合,每个属性包含一个原始值、对象或函数。存储在对象属性中的函数被称为方法。

我猜这意味着在不同的JavaScript实现中,不能依赖属性按照一致的顺序被枚举。(依赖语言的具体实现细节是不好的编码风格。)

如果你希望定义顺序,你需要实现一些定义顺序的方法,比如使用一个排序后的键数组来访问对象。

0
0 Comments

在这段代码中,通过使用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中,遍历的顺序是按照属性的插入顺序,但是属性名没有被正确引用。

解决这个问题的方法是不要依赖于属性的顺序。因为规范中对于遍历顺序没有做具体要求,不同的引擎实现也有所不同。如果需要有序的遍历,可以将属性名保存在一个数组中,并按照需要进行排序。

这段代码中出现的问题是不同浏览器对于遍历对象属性的顺序处理不一致,解决方法是不要依赖于属性的顺序。

0
0 Comments

在"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中,属性的顺序都是不确定的。在实际开发中,如果顺序对你很重要,应该使用数组来存储数据。

0