Javascript 效率:'for' 与 'forEach'

IT技术 javascript loops for-loop foreach
2021-01-21 05:35:16

2017 年 Javascript 中 for() 循环与 .forEach 的当前标准是什么。

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

这是否自课程编写(大约 2015 年)以来发生了变化,或者它们各自的真​​正优点和缺点,随着更多的经验,人们会学到什么。

任何建议将不胜感激。

1个回答

为了

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

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

这并不是说for循环总是更有效,只是 JS 引擎和浏览器已经优化了它们。多年来,对于哪种循环结构更有效(for、while、reduce、reverse-while 等)一直存在妥协——不同的浏览器和 JS 引擎都有自己的实现,提供不同的方法来产生相同的结果。随着浏览器进一步优化以满足性能需求,理论上[].forEach可以以更快或与for.

好处:

  • 高效的
  • 早期循环终止(荣誉breakcontinue
  • 条件控制(i<n可以是任何东西,不受数组大小的限制)
  • 变量范围(循环结束后可用的var i叶子i

为每个

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

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

好处:

  • 不涉及变量设置(迭代数组的每个元素)
  • 函数/箭头函数作用域变量到块
    在上面的例子中,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一次,缓存变量并优化你的代码。

for 循环在调试方面通常具有优势:进入、断点和检查它们是微不足道的。使用 forEach() 额外的回调级别会使事情变得有点复杂。
2021-03-15 05:35:16
优秀、彻底、不冒昧的答案,不受单一时间点、实施或微基准测试的约束。
2021-03-27 05:35:16
@Microsis 这里没有理由,当时可能是微优化,但这是不可避免的浏览器/引擎选择。由于它们位于示例中,因此它们是等效的。有时在我的例子中,我尝试展示一种稍微不同的使用语法来让新手思考的方式。人们经常看到i++,但会++i引起注意并导致发现 for 循环的最后部分是一个表达式,它可以用于许多操作,而不仅仅是设置循环增量。
2021-03-27 05:35:16
我真的很喜欢这个答案和短语中的解释[...], if performance and optimization was everything, there would be no other code than machine or assembly.我相信通过let声明块作用域局部变量语句, 的第二个好处forEach不再是for循环的优势,除非在不支持let.
2021-04-07 05:35:16
我要补充一点,这个答案可以使用一些更正更新或附录。例如,现在许多浏览器在内部优化字节码,因此如果满足某些条件,则重复操作一次。我认为如果数组在循环体中没有受到影响,那么它只会检索arr.length一次。我欢迎更熟悉的人来权衡。
2021-04-07 05:35:16