JS使用splice遍历解析后JSON数组为何出现隔项删除异常
数组按规则删除条目出现隔项失效问题
问题复现场景
- 输入待处理的已解析JSON数组结构:
[ { "idArticle": "1", "language": "SK" }, { "idArticle": "2", "language": "SK" }, { "idArticle": "3", "language": "SK" }, { "idArticle": "4", "language": "SK" } ]
- 触发条件:设置
let lang = "x",按照业务逻辑规则,应当保留language字段值等于lang转大写结果的条目,删除不匹配项。由于所有条目的language值为SK,不等于转换后的X,预期结果为清空整个数组。 - 实际运行异常:仅删除
idArticle为 1、3 的条目,最终保留 id 为 2、4 的两个条目,与预期完全不符。
存在缺陷的问题代码:
function cutArticleList(data) { for (i in data) { if (data[i].language === lang.toUpperCase()) { continue; } else { data.splice(i, 1); } } res.send(data); }
问题根因
隔项删除的效果是两个问题叠加导致的:
- 正向遍历+就地
splice删除的索引位移冲突:data.splice(i, 1)会直接修改原数组,删除当前索引位置的元素后,原本排在i+1位置的元素会向前移动一位,占据当前i的位置。此时循环继续按原有步长递增索引,会直接跳过这个刚前移的元素,转而处理i+2位置的内容,自然形成删一个漏一个的隔项效果。
结合本次场景的实际执行流程:- 第1轮循环i=0,删除索引0处id为1的条目,原数组变为
[id2, id3, id4],原id3元素移动到索引1的位置 - 第2轮循环i=1,处理当前索引1处的id3条目,将其删除,原数组变为
[id2, id4],原id4元素移动到索引1的位置 - 循环结束,最终保留位置在索引0、2的id2、id4,和实际运行结果完全匹配
- 第1轮循环i=0,删除索引0处id为1的条目,原数组变为
for...in遍历数组的设计缺陷:for...in本质是遍历对象的可枚举属性,并非为数组有序遍历设计,在原数组被动态修改时,更容易出现索引错位的问题。
修复参考方案
- 采用反向遍历方式删除元素:从数组最后一个索引向前遍历,此时删除当前索引位置的元素,不会影响前方尚未遍历元素的索引位置,从根源避免漏检。
- 使用数组原生
filter()方法生成符合规则的新数组返回,不直接修改原数组,规避动态索引变化的问题。 - 正向遍历场景下,执行
splice删除操作后,手动将当前索引值减1,抵消删除操作带来的位移影响。
内容的提问来源于stack exchange,提问作者mdupdevelop
相关产品推荐
相关产品推荐

