Javascript 在数组中循环时从数组中删除项目会破坏循环吗?对此我能做些什么?

Javascript 在数组中循环时从数组中删除项目会破坏循环吗?对此我能做些什么?,javascript,Javascript,我在这样的数组中循环 onScreenData.getTasks().array.forEach(function (task, taski, array) { if(task.checked){ myTasks.addTask(task, state.name) onScreenData.removeTask(taski); } }) onscreenda.removeTask()包含tasks.array.splice(索引,1)。Tasks

我在这样的数组中循环

onScreenData.getTasks().array.forEach(function (task, taski, array) {
    if(task.checked){
        myTasks.addTask(task, state.name)
        onScreenData.removeTask(taski);
    }
})

onscreenda.removeTask()
包含
tasks.array.splice(索引,1)。Tasks.array与循环使用的数组相同。当
tasks.array.splice(索引1)时运行时,循环立即停止。对此可以做些什么?

根据ECMA脚本5.1标准规范

forEach处理的元素范围在第一次调用callbackfn之前设置。调用forEach开始后附加到数组的元素将不会被callbackfn访问。如果数组的现有元素发生更改,则传递给回调的值将是forEach访问它们时的值在forEach调用开始之后和被访问之前删除的元素不会被访问。

为了更好地理解这一点,请检查以下代码

var a = [1, 2, 3, 4];

a.forEach(function(currentItem, idx, array) {
    console.log(a.length, currentItem, idx, array);
    a.splice(idx, 1);
});

console.log(a);
它输出

4 1 0 [ 1, 2, 3, 4 ]
3 3 1 [ 2, 3, 4 ]
[ 2, 4 ]
在第一次迭代中,
a.length
4
,当前项为
1
,索引为
0
。这很好。在第一次迭代中,我们删除了索引
0
处的元素

在第二次迭代中,由于删除了第一个元素,数组的长度缩短为3,
2
成为第一个元素,当前索引为
1
。现在,与索引
1
对应的项目是
3
。因此,这在本次迭代中被删除

现在,数组的长度为
2
,当前索引变为
2
。因为,当数组本身的大小为
2
时,我们无法访问索引2处的元素,所以JavaScript中断了循环

因此,我们实际上跳过了要删除的元素旁边的元素

这就是为什么我们不应该在迭代数组时修改它

这里最好的选择就是这样使用

onScreenData.array = onScreenData.getTasks().array.filter(function (task) {
    if(task.checked) {
        myTasks.addTask(task, state.name)
        return false;
    }
    return true;
});

@克里斯托弗:将阵列项目推送到新阵列。然后将其用于您的程序我看到一个建议是向后循环数组,这是一个更好的解决方案吗?还有,我如何使用它来删除任务?@Kristofernolgren我正在编辑答案,以包括为什么在迭代时删除是不好的,请检查
过滤器
版本。我们正在将结果分配给screenda.array上的
,对吗?这将只包含过滤后的数据。因此,如果
任务.checked
true
,则这些项目将被删除。非常实用且具有教育意义!需要明确的是:过滤完成后,我在新数组中循环,并在screenda.removeTask(taski);?