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

JavaScript中destroyer函数splice删数组元素结果异常修复

错误根因

你当前的for循环搭配splice的写法不符合预期,核心问题是数组调用splice删除元素后会发生原位塌陷:删除下标i的元素后,i后面所有元素都会自动往前移动1位,数组长度减1,但循环的计数变量i还是会照常执行i++自增,直接跳过了被删位置后紧跟的第一个元素,导致漏判。
拿你的测试用例destroyer([3, 5, 1, 2, 2], 2, 3, 5)走一遍执行流程就能直观看到问题:

  1. 初始i=0,arr[0]是3,属于待删除值,执行splice后数组变为[5,1,2,2],随后i自增到1
  2. 此时i=1对应的元素是1,本来待删除的5因为数组前移到了下标0的位置,直接被跳过
  3. 后续遍历到i=2时元素是2,执行splice删除后数组变为[5,1,2],i自增到3,超出当前数组长度(长度为2),循环直接结束,最终返回结果错误。
修复代码

保留for循环+splice的实现逻辑,有两种成熟的改法:

方案1:倒序遍历数组

从数组最后一个元素往前遍历,此时删除当前下标的元素,不会影响还没遍历到的前面元素的下标,不会出现漏判:

function destroyer(arr, ...rem) {  
  for(let i = arr.length - 1; i >= 0; i--) {      
      if (rem.includes(arr[i])) {
        arr.splice(i, 1);
      }    
  }
  return arr;  
}

console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5)); // 输出 [1],符合预期

方案2:正序遍历时删除元素后回退下标

如果要保留正序遍历的写法,每次执行splice删除后把i减1,抵消元素前移带来的下标偏移:

function destroyer(arr, ...rem) {  
  for(let i = 0; i < arr.length; i++) {      
      if (rem.includes(arr[i])) {
        arr.splice(i, 1);
        i--; // 回退下标,避免跳过紧接的元素
      }    
  }
  return arr;  
}

console.log(destroyer([3, 5, 1, 2, 2], 2, 3, 5)); // 输出 [1],符合预期

你提到的arr.filter(val => !rem.includes(val))是更推荐的实现方式:不会修改原数组,没有下标偏移的隐式问题,代码可读性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:24:23