Javascript效率:“ for” vs“ forEach”


103

2017年使用for()循环与.forEach的Javascript当前标准是什么?

我目前的工作我的方式,通过柯尔特史蒂尔斯的“Web开发训练营”在Udemy他热衷forEachfor他的教导。但是,作为课程工作的一部分,我在练习中搜索了各种东西,并且我发现越来越多的建议使用for-loop而不是forEach。大多数人似乎认为for循环更有效。

这是自编写本课程以来(大约2015年)以来发生的变化,还是它们各自的真​​正优缺点,您将通过更多的经验中学到这一点。

任何建议将不胜感激。


11
为什么将自己与某人对2017年标准的主观观念联系在一起?采用永恒的标准,例如编写干净,可维护的代码,知道工程师正在努力使最常用的结构非常有效,然后在遇到特定的性能问题时针对性能进行优化

2
本地人for很难获得纯速度。forEach()每次迭代都调用一个回调;因此,这显然会带来一些开销。
佳能

1
作为开发人员,我几乎不使用或不使用它,大多数工作是通过map,filter或reduce方法完成的。
AT

12
@AT,只要您不是map纯粹用于迭代并丢弃其生成的新数组的人之一。我不知道仅此站点上的特定功能选择我就需要纠正多少人。
佳能

1
@canon同意,循环选择很重要,在选择时应牢记此类方法的输出和残留。我认为,出于可读性考虑,应避免使用普通的“ for循环”。
AT

Answers:


199

对于

for循环效率更高。它是一个循环结构,专门设计用于在条件为true时进行迭代,同时提供步进机制(通常用于增加迭代器)。例:

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

这并不是说for -loops总是会更高效,只是JS引擎和浏览器已经对其进行了优化。多年来,关于哪种循环构造更有效(折衷,减少,逆转等)一直存在折衷方案-不同的浏览器和JS引擎拥有自己的实现,这些实现提供了不同的方法来产生相同的结果。随着浏览器进一步优化以满足性能要求,从理论上讲[].forEach,它可以以更快的速度或与相当的方式实现for

好处:

  • 有效率的
  • 早期循环终止(荣誉breakcontinue
  • 条件控制(i<n可以是任何值,并且不限于数组的大小)
  • 变量范围(var ii循环结束后可用)

每次

.forEach是主要遍历数组(也遍历其他可枚举对象,例如MapSet对象)的方法。它们是较新的,并且提供的代码在主观上更易于阅读。例:

[].forEach((val, index)=>{
   ...
});

好处:

  • 不涉及变量设置(迭代数组的每个元素)
  • functions / arrow-functions将变量范围限定在块上
    在上面的示例中,val它将是新创建的函数的参数。因此,val在循环之前调用的任何变量在结束后都将保留其值。
  • 从主观上讲,它更易于维护,因为它可以更容易地识别代码在做什么—它遍历了可枚举的对象;而for循环可用于任何数量的循环方案

性能

性能是一个棘手的话题,通常在进行前瞻性或方法时需要一些经验。为了提前确定(开发时)可能需要多少优化,程序员必须对问题案例的过去经验有很好的了解,并对潜在的解决方案有很好的了解。

在某些情况下使用jQuery有时可能会太慢(有经验的开发人员可能会知道),而在其他情况下则可能不是很重要,在这种情况下,库的跨浏览器合规性以及易于执行其他功能(例如AJAX,事件处理)值得节省开发(和维护)时间。

另一个例子是,如果性能和优化是一切,那么除了机器或程序集外,没有其他代码。显然,事实并非如此,因为有许多不同的高级和低级语言,每种语言都有自己的取舍。这些权衡包括但不限于专业化,开发简便性和速度,维护简便性和速度,优化代码,无错误代码等。

方法

如果您对某些内容是否需要优化的代码不太了解,通常最好先编写可维护的代码。从那里,您可以测试并找出需要时需要注意的地方。

也就是说,某些明显的优化应该是一般实践的一部分,而无需任何思考。例如,考虑以下循环:

for (var i=0; i < arr.length; ++i ){}

对于循环的每次迭代,JavaScript都会arr.length在每个周期上检索,键查找成本计算操作。没有理由不应该这样做:

for (var i=0, n=arr.length; i < n; ++i){}

这做同样的事情,但是只检索arr.length一次,缓存变量并优化代码。


25
出色,彻底,不冒昧的答案,不限于单个时间点,实施或微基准测试。

1
完美,这正是我一直在寻找的东西,并且比视频提供了更多的深度。我真的很感激,因为它是新手,所以有很多东西要学习,而这些东西很容易跳过,只要无缘无故地相互偏爱就不会对您造成任何影响。非常感谢!
tonyrobbins

2
for循环通常在调试方面有一个优势:进入,断点和检查很麻烦。使用forEach(),额外的回调级别可能会使事情复杂一些。
埃里克·格兰奇

1
@FelipeBuccioni谢谢,我实际上是要调查一下的,因为我认为引擎现在会检查数组是否会发生变异以确定长度是否被缓存。但是,出于遗留目的,我认为优化引擎并不那么慷慨,而每次迭代的长度都会影响性能。我会看一下您的文章,并在有时间的时候将其纳入答案,或者希望社区中的杰出成员可以为我做出修改:)
vol7ron

6
我真的很喜欢这个答案和这句话的解释[...], if performance and optimization was everything, there would be no other code than machine or assembly.。我相信使用let声明块范围局部变量的语句,除非在不支持的环境中,否则第二个好处forEach不再是for循环的好处let
user7393973 '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.