我应该为 JavaScript 数组和对象使用哪个 for 循环? [复制]

Posted

技术标签:

【中文标题】我应该为 JavaScript 数组和对象使用哪个 for 循环? [复制]【英文标题】:Which for loop should I use for JavaScript arrays and objects? [duplicate] 【发布时间】:2013-06-15 10:21:45 【问题描述】:

我在遍历数组时总是使用for (i=0; i<array.length; i++)

循环对象属性时,我总是使用for (var i in object)

我不能将for (i=0; ... ) 用于对象属性,但我可以for (var in ...) 用于数组,因为数组也是对象。

我要问的问题是:我应该完全转储for (i=0; ... ) 并将for (var in ...) 用于 数组和对象吗?有性能冲击吗?为什么我要使用一个而不是另一个?

【问题讨论】:

这几乎是一个重复,或者至少与an S.O. question viewed over 160K times密切相关。 @RayToal 我同意。这里的“相关问题”系统很好,但似乎还不够好。 :) 但是我担心另一个问题没有提出的一件事:性能 同意。很难知道问题何时几乎相同。但是,我链接到的那个应该有一些很好的理由来避免数组的 for-in,因此应该对您有所帮助。很好的一点是性能方面没有被涵盖! 实际上性能是在链接到 this article 的 cmets 之一中解决的 :) 【参考方案1】:

我应该转储for

你不应该。 for..in 用于循环数组时不关心索引,它也会列出附加到对象的属性。对数组使用for,对对象使用for..in

摘自MDN:

for..in 不应用于迭代索引顺序的数组 很重要...不能保证for..in 会以任何特定顺序返回索引,并且会返回所有可枚举的属性...

至于性能,我不担心,因为for..in循环索引数组显然不推荐。

【讨论】:

【参考方案2】:

我为你做了一个jsperf:

http://jsperf.com/for-vs-for-in43

基本上,它是在测试性能,使用for(var i in array) 时您会看到性能大幅下降。

话虽如此,你不应该放弃forfor for in

【讨论】:

+1 用于解决 OP 问题的性能。【参考方案3】:

不能将 for (i=0; ... ) 用于对象属性,但我可以使用 for (var in ...) 用于数组,因为数组也是对象。

您应该使用for,因为其他答案已经说明。

但是您可以使用Object.keys(yourObject) 将对象的键列为数组,然后在该数组上使用 for 循环。

var keys = Object.keys(myObject);
for(var i = 0, key; key = keys[i]; i++) 
    //...

【讨论】:

虽然由于浏览器支持我犹豫要不要使用它,但这听起来是个不错的方法。 +1 @Jared true,虽然支持非常好,但不包括旧版 IE 和 Opera:kangax.github.io/es5-compat-table 我正在倒计时,直到我可以停止支持 IE8。【参考方案4】:

如果您想要快速响应的代码,那么:

对于数组,while( l--)for(i=0,..) 循环是最快的...

在对象数组中,您只能使用 for in... 但如果您的代码很好,则不会经常发生循环遍历对象的情况。

最快的循环:

var myarray=[1,2,3,4,5,6],
length=myarray.length;//here i cache the length of the array.

缓存数组长度是保持代码快速的另一重要因素。

while(length--)
//do somethingwith your array
 //myarray[length];

while 是旧浏览器中最快的循环 .. 在新浏览器中,for 循环看起来要快一些。

for(var i=0;i<length;i++)
//do somethingwith your array
//myarray[i];

现在,如果您想定义变量,请在循环之前执行此操作。

还有一个很好的比较,即使有时代码写得不是很好,也可以向您展示性能。

http://jsperf.com/fors-vs-while/61

因此,如果您打算循环遍历数组,请始终使用 while-- 或 for(var i=0..) 缓存长度。

如果你在像 json 这样的多维对象中有数组,我真的很喜欢另一个循环是这个

for(var a=0,b;b=my.very.long.object[a];++a)
//do somethingwith your array 
//b

大多数人犯的另一个错误是他们在循环中使用 push... 在循环中执行 push 意味着你每次都执行一个新函数。 因为我们已经有了“i”作为索引,我们可以设置它并使用它直接存储数据,而无需执行新函数

所以

//wrong
for(var i=0,newArray=[];i<length;i++)
newArray.push(myarray[i]);//this is a waste of time and resources

//right
for(var i=0,newArray=[];i<length;i++)
newArray[i]=myarray[i];//we already have an index.

ps.:请随时纠正我糟糕的英语,但不要碰代码!.

【讨论】:

【参考方案5】:

还要注意,枚举的顺序是不能保证的,所以数组上的 for..in 可能会返回乱序的值。它还将列出所有属性,包括非数字属性(即不会通过迭代索引返回)和对象[[Prototype]] 链上的可枚举属性,因此您必须始终将其与 hasOwnProperty em> 测试你是否只想要自己的属性(最常见的情况)。

如果您使用的是 ES5 主机,那么您可以使用 Object.getOwnPropertyNames 和 Object.keys 之类的方法来获取自己的属性。但同样,订单无法保证。

最后,fordowhile 循环经过高度优化,性能差别很小,而且在一个浏览器中更快在另一个可能会很慢。仅在性能存在问题时才使用适合的并进行优化。

【讨论】:

以上是关于我应该为 JavaScript 数组和对象使用哪个 for 循环? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

我应该为 JavaScript 链接使用哪个“href”值,“#”还是“javascript:void(0)”?

应该使用哪个层从域对象转换为 DTO

jquery中遍历指定的对象和数组是哪个方法

在Javascript中按多个条件过滤数组

在 javascript 中将数组分箱以获得直方图

在javascript中将对象数组复制到另一个数组而没有对象引用(深拷贝)