修改 forEach 中的数组

Modifying array within forEach

本文关键字:数组 forEach 修改      更新时间:2023-09-26

我需要在 Array.forEach 中间插入一些东西到数组中。我想检查JavaScript如何处理这些情况。我期待任何事情,包括无限循环。但结果对我来说很奇怪。你能解释一下这里发生了什么吗:

var A = [0, 1, 2, 3, 4, 5, 6, 7]
A.forEach(function(x) {
   if (x == 3) A.splice(1, 0, 'new')
})
document.write(JSON.stringify(A))

通过观察大量的中间writeln s:

  1. forEach 循环只查看每个原始索引一次 - 因此它必须将数组的长度存储在某个临时变量中。

  2. splice行在同一位置插入"new":在第一个元素之后。

  3. 只有在看到第 4 个位置的"3"后,才会发生这种情况。

  4. 因此,在
  5. 第三次迭代中,在第一次插入之后,您的数组如下所示:

    [ 0, "new", 1, 2, 3, 4, 5, 6, 7 ]
    

    forEach迭代器位于元素 4 -- 又是"3"。

  6. .. 因此,"new"入到原始数组长度的其余部分。

forEach循环代码的编写者一定认为有人在后台更改了数组。一种稍微安全一点的方法是制作原始数组的副本,但我认为这需要一个拷贝(你无法提前知道更改的深度),这可能会导致大量的复制似乎是边缘情况。

你得到的是预期的行为,虽然它不是一个真正的无限循环 - 这是一个非生产性的循环。

您要在当前索引之前添加一个元素。这使得当前值发生偏移,因此您将在每次迭代时开始获得 x == 3。

这都是无限循环的前提,但是 JS forEach 为其设置了一个上限,该上限是原始数组中存在的元素数量。无论你如何操作数组,它都不能运行超过 8 次,这是原始长度。

此代码的输出最好地显示了正在发生的事情:

  var A = [0, 1, 2, 3, 4, 5, 6, 7]
  A.forEach(function(x, index) {
    document.writeln('A[' + index + '] = ' + x + '<br/>');
    if (x == 3) {
      A.splice(1, 0, 'new')
    }
  })
  document.write(JSON.stringify(A));

输出:

A[0] = 0
A[1] = 1
A[2] = 2
A[3] = 3
A[4] = 3
A[5] = 3
A[6] = 3
A[7] = 3
[0,"new","new","new","new","new",1,2,3,4,5,6,7]
好的,

让我们按步骤进行:

  1. 您的循环正常迭代,直到元素"3"

  2. 在元素"3"上,
  3. 你的循环在数组的第一个位置上经过"new",如下所示:[0, new, 1, 2, 3, 4, 5, 6, 7],但是您的所有元素都在向右的一个位置移动,因此在循环的第 4 个元素的下一次迭代中再次"3",因为它被移动了。

  4. 他重复步骤 2 直到最后一个第 8 个元素,并且更多 4 次将"new"放在数组的第一个位置。如果您想粘贴"新"一次,请按照以下步骤操作:

    A.forEach(function(x) {
    if (x == 3) {A.splice(1, 0, 'new'); break;}})