2016-01-21 47 views
12

我横跨方法Array.splice的这种奇怪副作用跑,并蒸馏该代码下降到必要的最低限度,以重新创建去除值。是的,这很大一部分可以在array.filter的一行中完成,但是我对我是否犯了错误或是否有其他事情感兴趣。方法Array.splice从剩余的元素

var array = []; 
 

 
for (var i = 0; i < 10; i++) { 
 
    array.push({ 
 
    value: i 
 
    }); 
 
} 
 

 
array.forEach(function(item, index, intArray) { 
 
    if (item.value % 2 == 1) { 
 
    item.odd = true; 
 
    } else { 
 
    item.odd = false; 
 
    } 
 

 
    if (item.odd) { 
 
    console.log("Removing " + item.value); 
 
    intArray.splice(index, 1); 
 
    } 
 

 
}); 
 

 
console.log(array);

运行在奇数元素此JavaScript结果如预期被去除,但它也除去item.odd值卸下intArray物品2,4,6,和8。拼接线带回奇数数组元素,但它也为所有元素带回item.odd值。

我已经在FF和Chrome中测试过了。即使只有项目传入回调函数,通过array.indexOf计算索引,并从循环外部引用数组,该行为仍然存在。

+3

我想知道在循环播放时是否会编辑数组。也许'index'值是原始数组中的索引,而不是新修改的索引。 –

+0

我有类似的想法。不过,我认为这种情况下的错误是项目和索引不符合预期,所以太多或太少的元素被删除,而不是元素中的值消失。 另外,如果这是我会在寻找通过指数步入回调,并计算其在即时之间的差异的情况下 - 但他们的工作出了相同的做法。 –

回答

9

我认为,当你在拼接每个奇数的阵列中,forEach最终跳过的下一个项目,这是一个偶数。所以这些项目根本不会被修改。

var array = []; 
 

 
for (var i = 0; i < 10; i++) { 
 
    array.push({ 
 
    value: i 
 
    }); 
 
} 
 

 
array.forEach(function(item, index, intArray) { 
 
    console.log(item); // only prints out 0, 1, 3, 5, 7, 9 
 

 
    if (item.value % 2 == 1) { 
 
    item.odd = true; 
 
    } else { 
 
    item.odd = false; 
 
    } 
 

 
    if (item.odd) { 
 
    console.log("Removing " + item.value); 
 
    intArray.splice(index, 1); 
 
    } 
 

 
}); 
 

 
console.log(array);

换句话说,只有forEach一次访问每个索引。所以说它到达项目1,它在索引1处。它删除项目1.项目2现在在索引1处。但是索引1已经被访问,所以它移动到索引2处的项目,该项目现在是项目3.

+1

这可以解释为什么'0'是奇数属性中唯一的“偶数”项。 –

+0

通过代码 - 它看起来很适合我。我想我们必须选择允许在快照上操作的便利性,还是允许对正在操作的数组进行迭代修改。 –