在本文中,我想概述一下标准的 for 循环和 forEach() 方法背后的区别,并对它们各自带来的一些好处进行评论。
作为免责声明,请不要把标题当真。我写这篇文章的目的是为了让读者了解缺点,并提供一些关于什么时候可以或不可以使用 forEach() 的见解,仅此而已。
forEach 方法接受回调函数作为输入,对于要迭代的数组中的每个元素,将执行此回调函数。应该注意的是,回调函数可以接受一些可选参数。它们包括传递给函数的当前值,当前值的相应索引。forEach 函数还提供了一个可选的参数,用于在你的回调函数中定义。
考虑以下代码:
相应的输出为:
corgis - 0
are - 1
cool - 2
如果您不知道什么是短路,它指的是我们提前终止或跳过循环的一个迭代。当我们在使用 forEach() 的时候,没有办法利用短路,在我们的循环的所有情况下,我们将忍受与数组大小有关的线性运行时间。
我为什么要关心这个?想象一下,我们有10亿个元素的未排序数组,而我们想找到某个元素。假设我们非常幸运,并在循环的第一次迭代中找到了这个元素。实际上,我们希望尽早返回,因为我们已经找到了我们想要的东西,但是在实现 forEach() 的方式中,我们总是会遍历剩下的元素。对于此类问题,我们可能会使用 .findIndex() 方法。
在 forEach() 方法中,由于我们在每次迭代时都要调用一个回调函数,所以我们产生了一个额外的作用域开销,与原生的 for 循环相比会导致速度变慢。
与传统的 for 循环相比,我们有一个初始化语句、一个在每次迭代中求值的条件语句和一个在循环体递增后的执行阶段。相对于 forEach() 方法,我们必须在每次迭代时创建额外的函数调用,它的成本更低。
为了测试性能,我创建了一个计时器脚本,该脚本在初始化数组后跟踪执行时间。这两个循环在其体内都执行了一个简单的 O(1) 操作:
在开发软件时,创建可维护和可读的代码应该是头等大事。我认为在代码中继续使用 forEach() 是为了提高可读性。随着方法链几乎成为JAVAScript中数组的第二天性,使用 forEach() 循环来运行数组,而不是 for 循环,这样读起来会更好。
还应该注意的是,像上面的例子中的输入尺寸非常大的情况,往往不太可能出现。在合理的输入大小下,这两个回路的性能相对相同。
你是否愿意以牺牲可读性为代价,以更快的速度执行几毫秒的功能?
如果对你有所启发和帮助,可以点个关注、收藏、转发,也可以留言讨论,这是对作者的最大鼓励。
作者简介:Web前端工程师,全栈开发工程师、持续学习者。