JS for循环结合splice删除数组奇偶位置元素结果异常排查
问题根因
代码存在两个问题,核心错误是正向遍历数组的同时调用splice()修改原数组,引发索引错位,另有一处变量名笔误。
索引错位的具体执行逻辑
splice()删除元素后,被删位置后方的所有元素会自动前移1位,数组长度同步减1,但循环计数器i依旧按固定步长自增,会直接跳过部分元素的校验。我们以传入"odd"(预期删除原数组索引1、3、5的元素,剩余[90,28,26])为例拆解执行过程:
- 初始状态:i=0,数组为
[90,34,28,19,26,22],i为偶数不触发删除,i自增为1 - i=1:i为奇数,删除当前索引1的元素34,数组变为
[90,28,19,26,22],所有索引大于1的元素全部前移一位,i自增为2 - i=2:当前数组索引2的元素是原索引3的19,i为偶数不触发删除,i自增为3
- i=3:i为奇数,删除当前索引3的元素26,数组变为
[90,28,19,22],后方元素继续前移,i自增为4 - 此时数组长度为4,
i<array.length的循环条件不成立,遍历结束,最终输出错误结果[90,28,19,22]:本该被删除的19、22因为索引错位跳过了校验,被错误保留。
变量笔误
代码中定义的数组名为myArr,但调用函数时传入的是未定义的arr,如果不是贴代码时的抄写错误,代码运行会直接抛出引用错误。
修复方案
方案1:倒序遍历删除(保留原数组修改逻辑)
从数组末尾向前遍历,删除元素时只会影响已经遍历过的后方元素索引,不会干扰未遍历的前方元素,不会出现错位:
const myArr = [90,34,28,19,26,22]; function deleteData (array, occuranceType){ for (let i = array.length - 1; i >= 0; i--) { const isOddDel = occuranceType === "odd" && i % 2 !== 0; const isEvenDel = occuranceType === "even" && i % 2 === 0; if (isOddDel || isEvenDel) { array.splice(i, 1); } } } deleteData(myArr, "odd"); console.log(myArr); // 输出 [90, 28, 26],符合预期
方案2:filter生成新数组(推荐,无副作用)
不直接修改原数组,通过索引判断过滤出需要保留的元素,逻辑更简洁也不会出现索引问题:
const myArr = [90,34,28,19,26,22]; function deleteData (array, occuranceType){ return array.filter((_, index) => { return occuranceType === "odd" ? index % 2 === 0 : index % 2 !== 0; }) } const result = deleteData(myArr, "odd"); console.log(result); // 输出 [90, 28, 26],符合预期
内容的提问来源于stack exchange,提问作者Juan Yeremia
相关产品推荐
相关产品推荐

