如何在for-of循环中删除数组元素?filter方法是否是更优方案?
问题解答
直接在for-of循环中splice数组的问题
你目前的写法存在两个明确问题:
- 语法错误:循环声明的变量是
x,但循环体内用的是未声明的foo,直接运行会抛出引用错误 - 逻辑隐患:for-of循环生成迭代器时会拿到数组初始的长度和元素索引映射,遍历过程中用splice删除元素会导致数组整体索引前移,后续未遍历的元素会被直接跳过。比如数组
[a,b,c,d]遍历到b(索引1)时将其删除,数组变为[a,c,d],下一次迭代会直接访问索引2的元素d,c就会被漏处理。
可行的实现方式
方案1:倒序遍历普通for循环(修改原数组)
如果确实需要直接修改原数组,可以用倒序遍历的写法,删除元素不会影响未遍历的部分:
for(let i = data.length - 1; i >= 0; i--) { const foo = data[i]; foo.bar = getValue(); if(foo.bar > 5) { data.splice(i, 1); } }
方案2:map+filter组合(更推荐)
你提到的filter方案是更符合现代JS编码习惯的写法,无副作用、逻辑清晰可读性更高,也不会出现索引偏移的隐患:
// 先统一给所有元素赋值bar属性,再过滤出符合条件的元素 const filteredData = data.map(foo => { foo.bar = getValue(); return foo; }).filter(foo => foo.bar <= 5);
如果不需要保留原数组,也可以直接把结果赋值给原来的data变量。
注意:上述map写法会修改原数组中元素对象的
bar属性,如果需要完全不改动原数据,可以在map中先拷贝对象再赋值。
内容的提问来源于stack exchange,提问作者klutt
相关产品推荐
相关产品推荐

