JavaScript 中最快的循环是什么?

举报
yd_244540595 发表于 2024/10/09 17:04:02 2024/10/09
【摘要】 作者:叶知秋水出处:juejin.cn/post/7420718380985319464无论使用哪种编程语言,循环都是一种内置功能。JavaScript 也不例外,它提供了多种实现循环的方法,偶尔会给开发人员带来困惑:哪一种循环才是最快的?顺便吆喝一声,技术大厂机会,前后端测试捞人,感兴趣来~以下是Javascript中可以实现循环的方法:For LoopWhile LoopDo-While...

作者:叶知秋水
出处:juejin.cn/post/7420718380985319464

无论使用哪种编程语言,循环都是一种内置功能。JavaScript 也不例外,它提供了多种实现循环的方法,偶尔会给开发人员带来困惑:哪一种循环才是最快的?

顺便吆喝一声,技术大厂机会,前后端测试捞人,感兴趣来~

以下是Javascript中可以实现循环的方法:

  • For Loop
  • While Loop
  • Do-While Loop
  • For-In Loop
  • For-Of Loop
  • ForEach Loop
  • Map Loop
  • Filter Loop
  • Reduce Loop
  • Some Loop
  • Every Loop
  • Find Loop

我们将对这些循环方法进行测试,以确定哪种方法最快。

为了比较每个循环的性能,我们将使用 console.time() 和 console.timeEnd() 方法来测量它们的执行时间。

console.time('My Description');

// Code to measure

console.timeEnd('My Description');

用于测试的任务是:将 5000 万个项目从一个数组转移到另一个数组。

console.time('Array Creation');
  
const numbersList = Array.from({ length: 50_000_000 }, () => Math.floor(Math.random() * 100));

console.timeEnd('Array Creation');

为确保公平比较,我们将异步运行每个循环。

虽然 For-In 的语法与 For-Of 类似,但它不是为数组设计的,因此不在测试之中。 For-In 更适合迭代具有多个属性的对象,因为它迭代的是属性名称(或键)而不是值本身,而与数组一起使用会导致性能问题和意外行为。

(async () => {
  await usingForLoop(numbersList);
  await usingWhile(numbersList);
  await usingDoWhile(numbersList);
  await usingForOf(numbersList);
  await usingForEach(numbersList);
  await usingMap(numbersList);
  await usingFilter(numbersList);
  await usingReduce(numbersList);
  await usingSome(numbersList);
  await usingEvery(numbersList);
  await usingFind(numbersList);
})()

ForLoop

const usingForLoop = async (array) => {
  console.time('FOR LOOP');

  const newNumbersList = [];
  for (let i = 0; i < array.length; i++) {
    newNumbersList.push(array[i]);
  }

  console.timeEnd('FOR LOOP');
}

while

const usingWhile = async (array) => {
 console.time('WHILE');

 let i = 0;
 const newNumbersList = [];
 while (i < array.length) {
   newNumbersList.push(array[i]);
   i++;
 }

 console.timeEnd('WHILE');
}

doWhile

const usingDoWhile = async (array) => {
 console.time('DO WHILE');

 let i = 0;
 const newNumbersList = [];
 do {
   newNumbersList.push(array[i]);
   i++;
 } while (i < array.length);

 console.timeEnd('DO WHILE');
}

ForOf

const usingForOf = async (array) => {
  console.time('FOR OF');

  const newNumbersList = [];
  for (const item of array) {
    newNumbersList.push(item);
  }

  console.timeEnd('FOR OF');
}

ForEach

const usingForEach = async (array) => {
  console.time('FOR EACH');

  const newNumbersList = [];
  array.forEach((item) => newNumbersList.push(item));

  console.timeEnd('FOR EACH');
}

Map

const usingMap = async (array) => {
 console.time('MAP');

 const newNumbersList = array.map((number) => number);

 console.timeEnd('MAP');
}

Filer

const usingFilter = async (array) => {
 console.time('FILTER');

 const newNumbersList = array.filter((item) => true);

 console.timeEnd('FILTER');
}

Reduce

const usingReduce = async (array) => {
 console.time('REDUCE');

 const newNumbersList = array.reduce((acc, item) => {
   acc.push(item);
   return acc;
 }, []);

 console.timeEnd('REDUCE');
}

Some

const usingSome = async (array) => {
 console.time('SOME');

 const newNumbersList = [];
 array.some((item) => {
   newNumbersList.push(item);
   return false;
 });

 console.timeEnd('SOME')
}

Every

const usingEvery = async (array) => {
  console.time('EVERY');

  const newNumbersList = [];
  array.every((item) => {
    newNumbersList.push(item);
    return true;
  });

  console.timeEnd('EVERY')
}

Find

const usingFind = async (array) => {
  console.time('FIND');

  const newNumbersList= [];
  array.find((item) => {
    newNumbersList.push(item);
    return false;
  });

  console.timeEnd('FIND')
}

任务运行了五次,显示的测量值是计算得出的平均值。

测试平均结果如下:

从结果可以看出,前5名分别是:

    1. Map
    1. For Loop
    1. While
    1. Do While
    1. For Each

有趣的是只有Map是一个函数调用,其余的都是循环体。

另外该测试仅针对一项特定任务进行的,不同测试用例可能会有不同的结果,不同的内存或者CPU也会有不一样的表现。从本次测试的结果,我们可以看到Map 和 For Loop 的性能是最好的。令人失望的是For-Of,相对于For Loop,作为新出的一个API竟然效率这么拉跨。

Map每次循环都需要调用回调函数,理论上不应该比For Loop更快。但现代 JavaScript 引擎(如 V8)对高阶函数(如 map、filter 等)进行了高度优化,尤其是对数组的处理。引擎内部可能会针对这些高阶函数应用特定的优化策略,减少不必要的操作,进而提升性能。而且 map 是一个专门用于遍历数组并返回新数组的高阶函数,V8 等引擎能够更好地预测和优化其内部的操作路径。而 for loop 是更通用的控制结构,可能没有这些特定的优化。

结论

1. 数组的length是每次重新获取的,这个会导致消耗时间,可以先把长度赋值给一个常量再使用
2. 计算用时console.time不够精确,用performance.now()
3. v8引擎会对代码进行优化和调整,先运行的代码可能会对后续代码产生影响,最好是单独测试
4. 测试时,先进行热身,让CPU处于稳定状态,也就是先随便跑个几十万的循环,后面再测试用例
5. 重复测试几次,取平均值
6. 长时间运行基准测试可能会消耗系统资源,如CPU、内存等,这可能会影响后续测试的性能,可以重置环境,也可以等个几秒进行下一轮测试

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。