当前位置:  开发笔记 > 编程语言 > 正文

元素在"for(... in ...)"循环中排序

如何解决《元素在"for(in)"循环中排序》经验,为你挑选了4个好方法。

Javascript中的"for ... in"循环是否按照声明的顺序循环遍历hashtables/elements?是否有一个浏览器没有按顺序执行?
我想要使​​用的对象将被声明一次,永远不会被修改.

假设我有:

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

我进一步使用它们:

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

在大多数体面的浏览器中,我可以期待'A:'你好''总是先来'B:'世界"吗?



1> Borgar..:

引用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"

这方面的技术性不如在任何时候可能发生变化的事实重要.不要依赖这样的事情.

简而言之:如果订单对您很重要,请使用数组.


"如果订单对您很重要,请使用数组":当您使用JSON时怎么样?
@ HM2K,同样的事情,spec说"对象是零个或多个名称/值对的无序集合." JSON不是JavaScript:服务器不需要(也可能不会)尊重您提供的订单.
Firefox自21版以来似乎不再尊重插入顺序了.
并不是的.Chrome与其他浏览器的订单不同:http://code.google.com/p/v8/issues/detail?id = 164
在ES2015中,此答案是错误的。

2> dvdrtrgn..:

一年之后就把这个搞得一团糟......

它是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);

当前浏览器中的要点或测试

Safari 5,Firefox 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"]

IE9

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


这有什么问题?正如规范所说,它是一个无序的键/值对列表.
@boxed:将对象视为哈希映射(table/whatever).在大多数语言(Java,Python等)中,这些类型的数据结构都没有排序.因此,在JavaScript中这也是同样的情况并不奇怪,它肯定不会使规范错误或愚蠢.
老实说,我没有看到这个答案(对不起).迭代属性的顺序是实现细节,浏览器使用不同的JavaScript引擎,因此预期订单会有所不同.这不会改变.
nickf:实现是正确的,因为他们做了规范所说的.我想每个人都同意javascript规范是......好吧,我不想用"错误"这个词,"非常愚蠢和讨厌"怎么样?:P
在现有技术实现中,由于受到真实数组的支持,您将按数值顺序接收整数属性,并且由于隐藏的类/形状公式,将按插入顺序接收命名属性.可能会有所不同的是它们首先列出整数属性还是首先列出命名属性.添加`delete`很有意思,因为至少在V8中,它会立即导致对象被哈希表备份.但是,V8中的哈希表按插入顺序存储.这里最有趣的结果是IE,我想知道他们做了什么样的丑陋来解决这个问题...

3> Tomalak..:

从ECMAScript语言规范,第12.6.4节(在for .. in循环中):

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

第4.3.3节("对象"的定义):

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

我想这意味着你不能依赖于JavaScript实现中以一致顺序枚举的属性.(依靠语言的特定于实现的细节,无论如何都是糟糕的风格.)

如果您希望定义订单,则需要实现定义它的内容,例如在使用它访问对象之前排序的键数组.



4> Adam Wright..:

for/in枚举的对象元素是未设置DontEnum标志的属性.ECMAScript,又名Javascript,标准明确地说"一个对象是一个无序的属性集合"(参见http://www.mozilla.org/js/language/E262-3.pdf第8.6节).

假设所有Javascript实现都将按声明顺序枚举,这将不符合标准(即安全).


这就是他提出问题的原因,而不仅仅是假设:p
推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有