JavaScript-如何在遍历数组时操作数组元素?
介绍
这是一个比较容易踩坑的操作,你一定要谨慎。
例子
我们希望删除一个数组中大于2的数字。
最容易写出来的解法:
// demo1
var a = [4, 5, 6];
for (var i = 0; i < a.length; i++) {
if (a[i] > 2) {
a.splice(i, 1);
}
}
console.log('处理之后的数组a为', a); // 处理之后的数组a为 [5]
为什么打印出来是 [5]
?
原因:在遍历数组的时候操作数组元素,数组会重新排列。
i为0时, length为3,数组为[4, 5, 6], 此时删除a[0] => 也就是4;
i为1时, length为2,数组为[5, 6], 此时删除a[1] => 也就是6;
i为2时, length为1,for循环不满足条件,终止。
你可以输入以下代码看看结果:
// demo2 我们将数组打印出来看看
var a = [4, 5, 6];
for (var i = 0; i < a.length; i++) {
console.log('index为', i);
console.log('value为', a[i]);
if (a[i] > 2) {
a.splice(i, 1);
}
}
console.log('处理之后的数组a为', a); // 处理之后的数组a为 [5]
结果:
index为 0
value为 4
index为 1
value为 6
处理之后的数组a为 [5]
正确解法
解法1
// 倒序删除,不会遗漏
var a = [4, 5, 6];
for (var i = a.length - 1; i >= 0; i--) {
if (a[i] > 2) {
a.splice(i, 1);
}
}
console.log('处理之后的数组a为', a); //[]
解法2
// filter函数
var a = [4, 5, 6];
var result = a.filter(function(value) {
return value <= 2;
});
console.log('处理之后的数组a为', a); //[]
结束语
可以在浏览器中调试上面的代码看看结果。
我们在遍历数组的时候,一定要谨慎地操作 (增加、删除、修改等) 数组元素,一不小心就会踩坑。
forEach 方法也会有同样的问题:
forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()) ,之后的元素将被跳过 - 参见下面的示例。
引自 mdn
Tags: