You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用forEach循环删除数组元素时,为何未被删除的元素未在控制台打印?

为什么在forEach中删除数组元素后,控制台只打印了部分元素?

这问题挺典型的,我来给你掰扯清楚为啥会出现这种情况~

先看你的代码:

const cartItems = ['Book1', 'Book2', 'Book3', 'Book4']
cartItems.forEach(function (item, index, array) {
    console.log(item)
    if (index == 0) {
        array.shift()
    }
    if (index == 1) {
        array.splice(1, 1)
    }
})
console.log(cartItems)

你预期forEach会遍历所有4个元素,但实际只打印了Book1和Book3,剩下的Book2和Book4没出现在控制台,核心原因是你在遍历过程中修改了数组的结构(删除元素),打乱了forEach的遍历逻辑。

一步步拆解你的代码执行过程:

  1. 初始数组:['Book1','Book2','Book3','Book4'],长度为4。forEach启动时,会按索引从0到3依次准备遍历。
  2. 第一次循环(index=0):
    • 打印Book1
    • 执行array.shift(),数组被修改为['Book2','Book3','Book4'],长度变成3。
  3. 第二次循环(index=1):
    • 注意!此时数组已经变了,当前index=1对应的元素是原来的Book3(原来的Book2现在跑到index=0的位置了)
    • 打印Book3
    • 执行array.splice(1,1),删除当前index=1的元素(也就是Book3),数组变成['Book2','Book4'],长度变成2。
  4. 第三次循环(index=2):
    • 现在数组的长度是2,最大索引是1,index=2已经超出了数组的有效范围,forEach直接终止循环,不会再执行后续的遍历。

所以到最后,只有Book1和Book3被打印,而Book2(现在在index=0,但forEach不会回头遍历已经处理过的索引)、Book4(还没轮到遍历它循环就结束了)都没机会被打印出来。

本质原因:

forEach的遍历逻辑是按初始的索引序列(0到初始length-1)依次访问,但每次访问时会检查当前索引是否在数组的有效范围内。当你在遍历中删除元素,数组的长度和元素位置都会变化,导致后续索引要么指向错误的元素,要么直接超出范围终止循环。这种情况下,很容易出现遍历不完整或者漏处理/重复处理元素的问题。

正确的做法:

如果你想删除特定索引的元素,不建议在forEach里操作,推荐这两种更稳妥的方式:

  1. 使用filter方法(最简洁):
    直接筛选出不需要删除的元素,返回新数组,不会修改原数组:
    const cartItems = ['Book1', 'Book2', 'Book3', 'Book4'];
    const filteredItems = cartItems.filter((_, index) => index !== 0 && index !== 2);
    console.log(filteredItems); // 输出 ['Book2', 'Book4']
    
  2. 倒序删除元素:
    如果一定要修改原数组,从后往前删除元素,这样前面的元素索引不会被打乱:
    const cartItems = ['Book1', 'Book2', 'Book3', 'Book4'];
    // 把要删除的索引从大到小排序,倒序遍历删除
    [0, 2].sort((a, b) => b - a).forEach(index => cartItems.splice(index, 1));
    console.log(cartItems); // 输出 ['Book2', 'Book4']
    

内容的提问来源于stack exchange,提问作者Muhammad Ali Malekzadeh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 19:47:34