为什么forEach arr.splice不能删除掉所有匹配上的元素?

为什么forEach arr.splice不能删除掉所有匹配上的元素?


let arr = [1,2,3,3,5]

arr.forEach((item, index) => {
    if (item === 3) {
        arr.splice(index, 1)  
    }
})

console.log(arr)  // [ 1, 2, 3, 5 ]
阅读 2.1k
3 个回答

就OP你的这个需求为什么不用 filter,而去使用 forEach + splice 呢?

let arr = [1,2,3,3,5]
arr = arr.filter(item=> item != 3)
console.log(arr)
// [1, 2, 5]

如果非要使用 splice 的话,应该是从后往前操作。
因为你 splice 删除掉其中一项之后,数组的下标就变更了,所以会跳过第二个 3

改成这样就可以了。

let arr = [1,2,3,3,5]
for(let i = arr.length-1; i >= 0; i--){
    if(arr[i]===3) arr.splice(i,1)
}
console.log(arr)
// [1, 2, 5]

这样破坏性的循环就算处理了也是有隐患和不利于理解的。
分析一下:
数组有五个元素
从循环次数分析,大概只循环走了4次,分别经过和对应:

0 1
1 2
2 3 
这里少了一次,因为index=2的时候删掉了,原来index=3的3变成了index=2
3 5  

换一个写法比较靠谱
1

let arr = [1,2,3,3,5]
let res = []
arr.forEach((item, index) => {
    if (item !== 3) {
        //arr.splice(index, 1)  
        res.push(item)
    }
})
// console.log(arr)  // [ 1, 2, 3, 5 ]
console.log(res)  // [1, 2, 5]

2

let arr = [1,2,3,3,5]
let res = arr.filter(item=>item !== 3)
// console.log(arr)  // [ 1, 2, 3, 5 ]
console.log(res)  // [1, 2, 5]
新手上路,请多包涵

splice方法是会改变原数组的,也就是,你使用splice删除一个元素之后,下一次循环的index依然加了一,但是数组少了刚刚删除的那个元素,
就你的代码而言,第一次匹配正确的index是2,下一个循环index加了1是3,但是现在的arr == [1,2,3,5],所以item是5,未匹配上,自然就不会再执行splice

MDN文档上对splice的定义说明

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏