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

使用splice与filter移除数组元素时,for...of遍历输出结果不同的原因解析

为什么filter重新赋值和splice修改原数组在for...of中输出不同?

首先得掰明白两个核心逻辑:for...of的遍历依赖于数组的迭代器,这个迭代器是在遍历开始时就绑定好当前数组的,再加上filter和splice对数组的修改方式完全不是一回事,结果自然不一样:

1. filter重新赋值:旧数组根本没被碰过

你在destroy方法里写的arr = arr.filter(...),本质是创建了一个全新的数组,然后把变量arr的指向从原来的旧数组切换到了新数组而已——旧数组本身还是完完整整的5个元素,一点没被修改。

而for...of在启动遍历的那一刻,就已经拿到了旧数组的迭代器,这个迭代器就像个死心眼的监督员,全程只盯着旧数组的元素。哪怕你把arr换成了新数组,它也不管,还是按旧数组的元素挨个打印,所以最终会输出1 2 3 4 5。

打个比方:你一开始抱着个装5个橘子的筐(旧数组),后来又买了个装4个橘子的新筐(filter后的新数组),并把手里的“筐标签”(变量arr)贴到了新筐上,但你正在数的还是原来那个旧筐里的5个橘子。

2. splice修改原数组:数组实时变化,迭代器跟着索引走

splice是直接在原数组上动手——删掉元素后,后面的元素会自动往前挪位置,数组长度也会立刻缩短。

咱们一步步拆解遍历过程:

  • 初始arr2是[t1, t2, t3, t4, t5](对应s值1到5)
  • 遍历第1个元素t1:打印1,没触发destroy2
  • 遍历第2个元素t2:打印2,没触发destroy2
  • 遍历第3个元素t3(s=3):触发destroy2,splice删掉了索引2的元素,此时数组变成[t1, t2, t4, t5],长度从5变4
  • 接下来迭代器要去取索引3的元素(因为之前已经遍历到索引2了),但此时数组的索引3是t5(s=5),于是直接打印5,跳过了原来的t4(现在它在索引2,但迭代器不会回头重新遍历索引2)

这就导致输出变成了1 2 3 5,漏掉了原来的4。

想验证的话可以试试这两个小改动

  • 如果想让filter的情况和splice结果一致,别重新赋值数组,直接修改原数组:

    destroy() {
      const index = arr.indexOf(this);
      if (index !== -1) {
        arr.splice(index, 1);
      }
    }
    

    这样遍历的时候迭代器盯着的原数组被修改,结果就会和splice的情况一样。

  • 如果想让splice的情况遍历完整元素,可以先复制一份数组再遍历:

    for (let t of [...arr2]) {
      // 遍历的是原数组的副本,splice修改原数组不影响副本的遍历
      if (t.s === "3") {
        t.destroy2();
      }
      console.log(t.s);
    }
    

    这时候就会输出1 2 3 4 5,因为迭代器盯着的是副本,原数组怎么改都不影响它。

内容的提问来源于stack exchange,提问作者0brine

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 13:02:40