JavaScript for...in vs for

472

你认为for...in和for循环有很大的区别吗?你更喜欢使用哪种“for”?为什么?

假设我们有一个关联数组的数组:

var myArray = [{'key': 'value'}, {'key': 'value1'}];

所以我们可以进行迭代:

for (var i = 0; i < myArray.length; i++)

并且:

for (var i in myArray)

我没有看到很大的差别。有性能问题吗?


13
请注意,我们在JS 1.6中也有myArray.forEach(callback[, thisarg])方法。 - Benji XVI
14
@Benji array.forEach 实际上是 ES5 中的一个方法。 - mikemaccana
2
在 for-in 循环中,您需要一个条件语句,看起来像这样:if(myArray.hasOwnProperty(i)){true} - Eric Hodonsky
6
['foo', 'bar', 'baz'].forEach(function(element, index, array){ console.log(element, index, array); });除了 IE8 及以下版本外,这个语法基本上可以在任何地方使用,并且它是目前最优雅的语法。 - Jon z
5
ECMAScript 6中,还有一个名为for...of的语句,例如:for (let i of myArray) console.log(i);。它可以遍历一个可迭代对象(如数组),并使用变量i来迭代该对象中的每个元素。在循环体内部,您可以对每个元素执行任何操作。 - Vitalii Fedorenko
23个回答

7

根据引用项目的方式,我会使用不同的方法。

如果只需要当前项目,请使用foreach。

如果需要索引器进行相对比较(即与上一个/下一个项目进行比较),请使用for。

我从未注意到性能差异。在担心之前,最好等待出现性能问题。


请参考Bnos的答案——for...in在这里并没有做你期望的事情,如果你使用它,可能会有各种有趣的问题。值得一提的是,Prototype以正确的方式处理这些事情。 - marcus.greasly

4

请注意!

如果你有多个 script 标签,且需要在标签属性中搜索信息,你需要使用 for 循环和 .length 属性,因为它不是一个简单的数组,而是一个 HTMLCollection 对象。

https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCollection

在大多数浏览器中,如果你使用 foreach 语句 for(var i in yourList),它会返回 HTMLCollection 的属性和方法!

var scriptTags = document.getElementsByTagName("script");

for(var i = 0; i < scriptTags.length; i++)
alert(i); // Will print all your elements index (you can get src attribute value using scriptTags[i].attributes[0].value)

for(var i in scriptTags)
alert(i); // Will print "length", "item" and "namedItem" in addition to your elements!

即使getElementsByTagName应该返回一个NodeList,大多数浏览器会返回一个HTMLCollection: https://developer.mozilla.org/en/DOM/document.getElementsByTagName

4

使用for (var i in myArray),您可以循环遍历对象,i将包含键名,您可以通过myArray[i]访问属性。此外,任何您添加到对象中的方法也将包含在循环中,例如,如果您使用任何外部框架(如jQuery或原型),或者直接向对象原型添加方法,则在某个时刻i将指向这些方法。


3
根据 jsperf,更短和更好的代码如下:
keys  = Object.keys(obj);
for (var i = keys.length; i--;){
   value = obj[keys[i]];// or other action
}

3
如果你真的想加速你的代码,那么这个怎么样?
for( var i=0,j=null; j=array[i++]; foo(j) );

在for语句中使用while逻辑,可以减少冗余。此外,Firefox具有Array.forEach和Array.filter功能。


2
为什么这会加速你的代码?我看不出为什么像这样重新排列语句会加速它。 - Rup

3

忘掉“你可能需要使用那个库”的说法。相反,要考虑到“你的JS可能会与使用该库的任何其他东西一起被包含”,因为问题仍然存在。 - ijw

3

我曾经遇到过使用对象、原型和数组的“for each”存在问题。

我的理解是,“for each”用于对象的属性,而不是数组。


2

for(;;) 是为了处理数组:[20,55,33]

for..in 是为了处理对象:{x:20,y:55:z:33}


1
使用Array().forEach循环来利用并行性。

4
浏览器中的JavaScript采用事件循环并发执行,因此Array.prototype.forEach不会并行执行多个回调调用。 - Mike Samuel

0

两者之间有一个重要的区别。for-in循环遍历对象的属性,因此当情况是数组时,它不仅会遍历其元素,还会遍历它具有的“remove”函数。

for (var i = 0; i < myArray.length; i++) { 
    console.log(i) 
}

//Output
0
1

for (var i in myArray) { 
    console.log(i) 
} 

// Output
0 
1 
remove

你可以使用带有 if(myArray.hasOwnProperty(i)) 的 for-in 循环。不过,当迭代数组时,我总是更喜欢避免这种情况,而是使用 for(;;) 语句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接