元素顺序在“for (...在...)”圈

2022-08-30 00:58:44

“对于...in“循环 在 Javascript 中循环通过哈希表/元素的声明顺序?有没有一个浏览器没有按顺序进行?
我希望使用的对象将被声明一次,并且永远不会被修改。

假设我有:

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

我进一步将它们用于:

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

我可以期望在大多数像样的浏览器中,“A:”Hello“总是在”B:“世界”之前吗?


答案 1

引用John Resig的话

目前,所有主流浏览器都按照对象的定义顺序循环访问对象的属性。Chrome也这样做,除了少数情况。[...]此行为由 ECMAScript 规范显式保留。在 ECMA-262 中,第 12.6.4 节:

枚举属性的机制...取决于实现。

但是,规范与实现完全不同。ECMAScript 的所有现代实现都按照对象属性的定义顺序对其进行迭代。因此,Chrome团队认为这是一个错误,并将对其进行修复。

所有浏览器都遵循定义顺序,但Chrome和Opera除外,它们对每个非数字属性名称都这样做。在这两个浏览器中,属性按顺序拉取在第一个非数值属性之前(这与它们如何实现数组有关)。顺序也是一样的。Object.keys

此示例应明确发生的情况:

var obj = {
  "first":"first",
  "2":"2",
  "34":"34",
  "1":"1",
  "second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"

这方面的技术细节不如它可能随时改变的事实重要。不要依赖事物保持这种状态。

简而言之:如果顺序对您很重要,请使用数组。


答案 2

一年后碰到这个...

现在是2012年,主要的浏览器仍然不同:

function lineate(obj){
    var arr = [], i;
    for (i in obj) arr.push([i,obj[i]].join(':'));
    console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */  lineate(obj);
obj.a = 4;
/* log2 */  lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */  lineate(obj);

在当前浏览器中进行要点或测试

野生动物园 5, 火狐 14

["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]

Chrome 21, Opera 12, Node 0.6, Firefox 27

["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]

十六进制

[123:xyz,a:1,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
[123:xyz,a:4,b:2,c:3]