在将Array.reduce应用于数组时改变数组有什么后果

时间:2017-06-21 17:12:16

标签: javascript arrays reduce

假设我有一个数组:

const ar = [1,2,3,4];

我将reduce函数应用于它,在该函数内部我删除了这样的元素:

ar.reduce((result, element, index, original)=>{
    original.pop();
}, []);

对于前两个元素,该函数仅执行两次。这是可以理解的,因为我在之前的电话中删除了第3和第4个元素。

但有趣的是,如果我执行该函数并删除当前元素:

ar.reduce((result, element, index, original)=>{
    original.splice(index, 1);
}, []);

对于前两个元素,该函数仍然执行两次。为什么不对3rd4th元素执行它们,因为它们保留在数组中?

这种行为是否记录在任何地方?在一个规格可能吗?

1 个答案:

答案 0 :(得分:3)

在你的第二个例子中,它实际上是为 1st 3rd 元素执行的,而不是前两个元素:



const ar = [1, 2, 3, 4];

ar.reduce((result, element, index, original)=>{
    console.log(element, index);
    original.splice(index, 1);
}, []);

console.log(ar);




1 2 3 4
^

此处,虽然reduce element1index0,但它会调用splice,删除第一个元素,然后迭代到下一个索引:

2 3 4
  ^

此处,简化element3index1。删除后,index将等于ar.length,它会停止,并留下

2 4

reduceRight()仍将访问所有元素的原因是因为您向后迭代,并且前一个元素位置不受在当前索引处拼接元素的影响:



const ar = [1, 2, 3, 4];

ar.reduceRight((result, element, index, original)=>{
    console.log(element, index);
    original.splice(index, 1);
}, []);

console.log(ar);




演练:

element = 4, index = 3

1 2 3 4
      ^

element = 3, index = 2

1 2 3
    ^

element = 2, index = 1

1 2
  ^

element = 1, index = 0

1
^

要回答您的问题,请{是ECMAScript documents this behavior for Array#reduce() as part of the specification

  

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

与上述完全相同的段落也适用于reduce

以下是reduceRight的填充物,遵循规范中的步骤:

Array#reduce()