JavaScript forEach 按数组顺序执行的三个维度分析

 更新时间:2026年01月10日 09:35:05   作者:亮子AI  
文章分析了JavaScript中forEach在同步和异步代码中的行为,指出它在异步情况下不会按顺序等待任务完成,这是常见的陷阱,文章还介绍了几种替代forEach处理异步任务的方法,推荐使用for...of和reduce,以及在需要并发时使用map和Promise.all,感兴趣的朋友跟随小编一起看看吧

简单直接的回答是:是的,在同步代码中,forEach 是严格按照数组索引顺序(从 0 到 length-1)执行的。

但这里有一个巨大的陷阱:虽然它按顺序“启动”任务,但它不会等待异步操作(如 Promise)完成。

下面从三个维度详细分析:

1. 同步代码:严格顺序执行

如果你在 forEach 中执行的是纯同步逻辑,它会从头到尾依次执行:

const arr = [1, 2, 3];
arr.forEach(num => {
  console.log(num);
});
// 输出顺序永远是: 1, 2, 3

2. 异步代码:顺序启动,但不顺序等待(最常见的坑)

当你把 async/await 放在 forEach 中时,forEach 不会等待上一个循环的任务完成才开始下一个。

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const arr = [1, 2, 3];
async function test() {
  console.log('开始');
  arr.forEach(async (num) => {
    await delay(1000 / num); // 不同的延迟时间
    console.log(num);
  });
  console.log('结束');
}
test();
// 实际输出顺序:
// 开始
// 结束
// 3 (延时最短,先完成)
// 2
// 1 (延时最长,最后完成)

原因: forEach 内部的逻辑大致是这样的:for (let i = 0; i < len; i++) { callback(arr[i]); }。它只是简单地调用了回调函数,并没有 await 回调函数的返回值。

3. 特殊规则:跳过“稀疏”位置

forEach 会跳过数组中已删除或未赋值的项(空位),但不会跳过 undefined

const arr = [1, , 3]; // 索引 1 是空位
arr.forEach((num, i) => console.log(i, num));
// 输出:
// 0 1
// 2 3
// (跳过了索引 1)

总结与最佳实践

如果你需要严格按顺序执行异步任务(即:任务1完成 -> 任务2开始),请不要使用 forEach,改用以下方式:

方法 A:使用for...of(推荐)

for...of 能够正确处理 await

for (const num of arr) {
  await doSomethingAsync(num); // 这里会严格等待
}

方法 B:使用reduce

arr.reduce(async (promise, num) => {
  await promise;
  await doSomethingAsync(num);
}, Promise.resolve());

方法 C:如果你不需要顺序,只需要并发

如果你希望所有任务同时开始并等待全部结束,使用 map 配合 Promise.all

await Promise.all(arr.map(async (num) => {
  await doSomethingAsync(num);
}));

结论: 在处理同步逻辑时,forEach 是顺序的;在处理 async/await 异步逻辑时,它会导致“并发”执行(实际上是顺序启动,乱序结束),这通常不是你想要的结果。

到此这篇关于JavaScript forEach 按数组顺序执行的三个维度分析的文章就介绍到这了,更多相关js foreach数组顺序执行内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中的事件循环机制解读

    JavaScript中的事件循环机制解读

    本文全面介绍了JavaScript的事件循环机制,包括其基本概念、组成部分、任务队列的详细解释、完整的执行流程、实际代码演示、浏览器与Node.js的区别、常见面试题分析以及性能优化技巧,通过记忆口诀“同微宏,微先走,宏之后,微清空”,帮助读者更好地理解和应用事件循环机制
    2025-10-10
  • echarts饼图指示器文字颜色设置不同实例详解

    echarts饼图指示器文字颜色设置不同实例详解

    在默认的饼状图里面,图例legend颜色是黑色的,有时候根据ui需要,根据不同的背景色,需要将图例文字调成白色或者其他颜色,下面这篇文章主要给大家介绍了关于echarts饼图指示器文字颜色设置不同的相关资料,需要的朋友可以参考下
    2022-07-07
  • 如何使用JS console.log()技巧提高工作效率

    如何使用JS console.log()技巧提高工作效率

    这篇文章主要介绍了如何使用JS console.log()技巧提高工作效率,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 在Z-Blog中运行代码[html][/html](纯JS版)

    在Z-Blog中运行代码[html][/html](纯JS版)

    在Z-Blog中运行代码[html][/html](纯JS版)...
    2007-03-03
  • 纯js实现隔行变色效果

    纯js实现隔行变色效果

    这篇文章主要为大家详细介绍了纯js实现隔行变色效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • 跨域解决之JSONP和CORS的详细介绍

    跨域解决之JSONP和CORS的详细介绍

    跨域常见的两种方式,分别是jsonp和cors,这篇文章主要介绍了跨域解决之JSONP和CORS的详细介绍,非常具有实用价值,需要的朋友可以参考下
    2018-11-11
  • 使用POST方式弹出窗口的两种方法示例介绍

    使用POST方式弹出窗口的两种方法示例介绍

    做一个功能需要弹窗,因为get方式对url的长度有限制,所以必须用post,本文有两个不错的方法,大家可以参考下
    2014-01-01
  • UNIAPP实现微信小程序登录授权和手机号授权功能(uniapp做微信小程序)

    UNIAPP实现微信小程序登录授权和手机号授权功能(uniapp做微信小程序)

    uniapp开发小程序,先授权用户信息后再出现手机号授权的页面进行手机号授权,完成后返回上一页面并把信息存入后台以及前台缓存中,方便使用,这篇文章主要介绍了UNIAPP实现微信小程序登录授权和手机号授权(uniapp做微信小程序),需要的朋友可以参考下
    2024-08-08
  • onclick与listeners的执行先后问题详细解剖

    onclick与listeners的执行先后问题详细解剖

    javascript中onclick与listeners的执行先后问题一直都是大家所疑惑的地方,接下来将为大家解决此疑惑,感兴趣的朋友可以了解下哦
    2013-01-01
  • JavaScript Window 打开新窗口(window.location.href、window.open、window.showModalDialog)

    JavaScript Window 打开新窗口(window.location.href、windo

    本文主要介绍了JavaScript Window 打开新窗口的三种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05

最新评论