for和forEach遍历数组,谁更快?

729 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情

我相信很多人在看到这个题目的时候,都已经知道了答案,for的速度更快。那么各位看官真的有自己测试过吗?它真的比forEach快吗?今天我突然上头就想自己测试一下,于是记录一下自己这次上头。

复杂度

前端重时间轻空间,二者的时间复杂度都是O(n);理论上速度应该差不多,接下来我们直接运行代码进行比较。

代码

const arr = [];
  for(let i = 0; i < 100 * 10000; i++){
    arr.push(i)
  }
  const len = arr.length;

  console.time('for')
  let n1 = 0;
  for(let i = 0; i < len; i++){
    n1 ++ 
  }
  console.timeEnd('for')//for: 3.90087890625 ms

  console.time('forEach')
  let n2 = 0;
  arr.forEach(() => n2++ )
  console.timeEnd('forEach')//forEach: 14.41015625 ms

结果

代码结果和我们了解到的for循环速度最快是一致的,但是从复杂度上来说,其速度应该差不多。虽然在100万次循环的加成下,其时间达到了3.5倍的关系,但在我们实际生产环境中很少用到如此大的数据量的循环。所以在实际生产中,我们可以优雅的使用forEach。虽然最“低级”的for更快,但这不影响在实际生产中使用其他方法遍历。

延展

  1. 为什么for会更快呢?
    在上方代码中for循环体中,直接进行了n++,而在forEach中,需要先创建一个匿名函数。这间接说明了创建函数也是会消耗时间的。这里不知道大家是否能想到另外一个问题:‘for循环和递归那个速度更快呢?’相信大家都明白了这两者应该是一样的。具体的比较大家可以看一下怎样求得斐波那契数列的第n个值呢?这篇文章,它展现了具体的速度比较。

  2. 对于数组的循环,你能想到多少方法?用这些方法遍历数组,速度如何呢? 我能想到的能够遍历数组的方法有:for、forEach、for in、for of、filter、some。
    其中filter和some相对而言会比较陌生
    filter:创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的元素
    some:检测数组中元素是否满足指定条件,返回true或false

和上方代码使用相同的循环次数同时进行遍历,得到如下数据
for: 3.90087890625 ms > forEach: 14.41015625 ms > some: 16.072021484375 ms > filter: 26.107177734375 ms > for of: 28.89404296875 ms >for in: 133.521728515625 ms;

上方数据在本地多次运行后得到相同的大小关系,比较稳定。

思考

延展2中对不同的遍历方式进行了速度比较,为什么for in会比其他的方式慢那么多呢?