为何filter方法中的if条件未生效?数组处理后仍存null元素
问题原因分析
你在filter回调里调用splice修改原数组,导致遍历索引混乱,最终残留null,核心原因是**filter的遍历次数和索引基于数组初始长度,而splice会实时改变数组的长度和元素位置,使得部分元素被跳过处理**。
具体执行过程拆解
初始数组:[null, null, null, "a"](长度4,索引0、1、2、3)
- 第一次循环(i=0):
- 当前元素是
null,执行splice(0,1),数组变为[null, null, "a"](长度3)。
- 当前元素是
- 第二次循环(i=1):
- 此时数组的索引1对应的是原数组的第三个
null(原索引2的元素),满足条件执行splice(1,1),数组变为[null, "a"](长度2)。
- 此时数组的索引1对应的是原数组的第三个
- 第三次循环(i=2):
- 数组当前长度是2,访问
a[2]得到undefined,不满足v===null,无操作。
- 数组当前长度是2,访问
- 第四次循环(i=3):
- 访问
a[3]同样是undefined,无操作。
- 访问
最终数组剩下[null, "a"],这个残留的null是原数组的第二个null(原索引1)——因为第一次删除后它移到了索引0,但filter接下来直接遍历i=1,跳过了这个位置的元素,导致从未被检查和删除。
正确的解决方式
方式1:直接用filter完成过滤(推荐)
filter本身的设计就是返回一个新数组,包含符合条件的元素,不需要修改原数组:
let a = [null, null, null, "a"]; const filteredA = a.filter(v => v !== null); // filteredA 结果为 ["a"],原数组a保持不变
如果一定要修改原数组,可以把过滤结果重新赋值:
a = a.filter(v => v !== null);
方式2:倒序遍历删除原数组元素
如果必须通过splice修改原数组,使用倒序for循环,这样删除元素不会影响未遍历的索引:
let a = [null, null, null, "a"]; for (let i = a.length - 1; i >= 0; i--) { if (a[i] === null) { a.splice(i, 1); } } // 最终a为 ["a"]
内容的提问来源于stack exchange,提问作者Deke
相关产品推荐
相关产品推荐

