JavaScript forEach循环中splice与filter删除元素的差异解析
核心原理说明
这两种操作的差异本质上是两个底层机制共同作用的结果:forEach的执行逻辑、splice和filter的数组操作特性。
1. 先明确forEach的运行规则
你调用arr.forEach()的瞬间,forEach就会捕获当前arr指向的原数组引用,同时固定初始遍历逻辑,整个遍历过程只会操作最开始拿到的这个数组对象,不会中途重新读取arr变量的最新指向。
2. splice影响遍历的原因
splice是修改性方法,直接对原数组的内存数据做改动,不会生成新数组:
你示例里的遍历过程是这样的:
- 初始原数组为
[1,2,3,4],forEach要遍历索引0到3 - 索引0:打印1,无修改
- 索引1:打印2,触发
splice操作,原数组直接被改成[1,3,4],长度从4变成3 - 索引2:现在原数组索引2位置的元素是4,直接打印4
- 索引3:原数组当前长度只有3,不存在索引3,遍历结束
所以最终打印结果是1,2,4。
3. filter不影响遍历的原因
filter是非修改性方法,它完全不会改动原数组,只会返回一个全新的数组对象:
你示例里写的arr = arr.filter(el => el !== 2),只是把arr这个变量的指向从旧数组改成了新生成的[1,3,4],但forEach最开始绑定的旧数组[1,2,3,4]本身没有任何变化,遍历全程还是对着旧数组走:
- 索引0:打印1
- 索引1:打印2,修改
arr变量指向新数组,旧数组不变 - 索引2:旧数组索引2是3,打印3
- 索引3:旧数组索引3是4,打印4
所以最终打印结果是1,2,3,4。
补充避坑提示
如果需要在遍历中删除数组元素,更稳妥的方式是直接用filter生成符合要求的新数组后再做后续操作,避免直接修改原数组带来的遍历异常。
内容的提问来源于stack exchange,提问作者n8o
相关产品推荐
相关产品推荐

