我见过许多建议使用的问题:
for (var i = 0; i < myArray.length; i++){ /* ... */ }
而不是:
for (var i in myArray){ /* ... */ }
对于数组,由于迭代不一致(see here)。
但是,我似乎找不到任何似乎更喜欢面向对象循环的东西:
myArray.forEach(function(item, index){ /* ... */ });
这对我来说似乎更直观。
对于我目前的项目,IE8的兼容性非常重要,我正在考虑使用Mozilla's polyfill,但我不能100%确定这是如何工作的。
答案 0 :(得分:121)
for
循环和forEach
方法之间最实质的区别在于,对于前者,您可能会break
退出循环。您只需从传递给continue
的函数返回即可模拟forEach
,但无法完全停止循环。
除此之外,两者有效地实现了相同的功能。由于变量提升,另一个微小差异涉及for循环中索引的范围(以及所有包含变量)。
// 'i' is scoped to the containing function
for (var i = 0; i < arr.length; i++) { ... }
// 'i' is scoped to the internal function
arr.forEach(function (el, i) { ... });
但是,我发现forEach
更具表现力 - 它代表了你迭代数组中每个元素的意图,它为你提供了对元素的引用,而不仅仅是索引。总的来说,它主要归结为个人品味,但如果您可以使用forEach
,我建议您使用它。
两个版本之间存在一些实质性差异,特别是在性能方面。事实上,简单的for循环比forEach
方法表现得更好,如this jsperf test所示。
这种表现是否对你来说是必要的取决于你自己决定,在大多数情况下,我更倾向于表达速度。这种速度差异可能是由于在稀疏阵列上运行时基本循环和方法之间的微小语义差异,如this answer中所述。
如果你不需要forEach
的行为和/或你需要尽早摆脱循环,你可以使用Lo-Dash的_.each
作为替代,它也可以交叉工作-browser。如果你正在使用jQuery,它也提供了类似的$.each
,只需注意每个变体中传递给回调函数的参数的差异。
(对于forEach
polyfill,如果您选择使用该路线,它应该可以在旧浏览器中正常工作。)
答案 1 :(得分:12)
您可以使用自定义foreach函数,该函数的性能远远优于Array.forEach
您应该在代码中添加一次。这将为数组添加新功能。
function foreach(fn) {
var arr = this;
var len = arr.length;
for(var i=0; i<len; ++i) {
fn(arr[i], i);
}
}
Object.defineProperty(Array.prototype, 'customForEach', {
enumerable: false,
value: foreach
});
然后你可以在任何地方使用它,比如Array.forEach
[1,2,3].customForEach(function(val, i){
});
唯一的区别是它快了3倍。 https://jsperf.com/native-arr-foreach-vs-custom-foreach
更新:在新的Chrome版本中,.forEach()的效果得到了改善。但是,该解决方案可以在其他浏览器中提供额外的性能。
答案 2 :(得分:4)
一些开发人员(例如Kyle Simpson)建议使用.forEach
来表明数组会产生副作用,.map
表示纯函数。 for
循环在这个等式中,然后,在我看来,作为一个通用的解决方案,它更容易沟通,因为当迭代次数被预先计算时,它被多种语言所支持。 / p>