为什么我必须先从我的论证中退出,然后再从我的数组中退出以从数组中删除一个项目?

Why do I have to pull from my argument before pulling from my array wrt to removing an item from an array?

这是我正在使用的代码:

const removeFromArray = function(arr) {
    let args = Array.from(arguments);
    for(let x=0; x<arr.length; x++) {
        for(let y=1; y<args.length; y++) {
            if(arr[x]===args[y]) {
                arr.splice(x,1);
            }
        }
    }
    return arr;
}

如果我将外循环与内循环切换,我可以让代码工作。

我只是无法从逻辑上弄清楚为什么如果我的外循环先从参数数组中提取它就不起作用。它适用于大多数事情,但它有问题,例如:

removefromArray([1,2,3,4], 3, 2)

它只删除了 2 个,剩下 3 个保持不变。

我想也许循环会删除 2 并将 3 下推到索引。 但在那种情况下,removeFromArray([1,2,3,4], 1, 2, 3, 4) 将不起作用,但它确实起作用。

我没有得到什么?

splice 将改变数组。如果您在 splice 的同时遍历数组,则必须小心将索引重置回以说明新重新排列的元素。例如[1, 2, 3, 4],如果2和3都符合条件则从数组中移除元素:

  • 在一次迭代中,x 将为 1,匹配值 2。2 将通过 splice 从数组中删除。然后数组将变为 [1, 3, 4].
  • 如果此时您增加 x,它将变为 2,因此将检查索引 2 处的项目。但是该索引处的项目现在是 4; 3 从未被检查过。或者,如果您增加 y 被检查参数的索引,那么刚刚删除的参数将不会再次被检查。

找到匹配项时手动递减索引

// Not recommended; verbose, ugly, and impure
const removeFromArray = function(arr) {
    let args = Array.from(arguments);
    for(let x=0; x<arr.length; x++) {
        for(let y=1; y<args.length; y++) {
            if(arr[x]===args[y]) {
                arr.splice(x,1);
                x--;
            }
        }
    }
    return arr;
}

console.log(removeFromArray([1,2,3,4], 3, 2));

或使用 .filter 代替:

const removeFromArray = (arr, ...toRemove) => arr.filter(
  item => !toRemove.includes(item)
);

console.log(removeFromArray([1,2,3,4], 3, 2));

还要确保使用相同的大写 - 如果您将函数定义为 removeFromArray,请确保使用大写 F 调用它。 (使用 removefromArray 会抛出 ReferenceError)