JS 的 forEach 的细节

494 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 29 天,点击查看活动详情

forEach() 方法是 for 循环的特殊简化版,用于调用数组的每个元素,并将元素传递给回调函数。

语法

array.forEach(callbackFn(currentValue, index, arr), thisValue)

image.png

如何中断 Foreach 循环

在 forEach 中使用 return 语句,既不会接收到返回值,也不会中断循环。(continue 、 break 也一样)

执行如下代码:

[1,2,3,4,5].forEach(item=>{
    if(item===3){
        return
    }
    console.log(item);
})

运行结果可看到输出了数组的全部内容:

image.png

中断 的方法:

  • 改为支持中断的循环:

    • for...of 循环
    • every() // return false 时中止循环
    • some() // return true 时中止循环
    • find()
    • findIndex()
  • 在需要中断的地方抛出异常(try /catch)

    try {
        [1, 2, 3].forEach(function(item) {
            if (item === 2) throw '循环终止';
            console.log(item);
        });
    } catch (e) {
        console.log(e);
    }
    

    运行结果:

    image.png

只支持同步代码

function doSomething() {
    let arr = [1,2,3];
    arr.forEach(async (item) => {
        const res = await getData(item);
        console.log(res);
    });
    console.log("end");
}

function getData(val) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(val);
        }, 500 * val);
    });
}

doSomething();

运行结果:

image.png

可以看到 end 先于 forEach 循环中的输出,说明当 forEach 中包含异步代码时,不会阻塞后面代码的执行。

如果想要获取正常顺序的结果,可以使用 for...of 或是 普通 for 循环来实现(通过迭代器的方式遍历)

async function doSomething() {
    let arr = [1,2,3];
    for (const item of arr) {
        const res = await getData(item);
        console.log(res);
    }
    console.log("end");
}

运行结果:

image.png

forEach 和 map

相同点:

  • 遍历数组
  • 回调函数都支持三个参数:item(当前的每一项),index(索引),arr(原数组)

不同点:

  • 当不对数据本身进行修改时使用 forEach(),要改变数据值的时候使用 map()
  • map()会分配内存空间存储新数据并返回,forEach()不会返回数据