【问题标题】:# of looping cycles after adding new elements during iteration. forEach vs for/of# 在迭代期间添加新元素后的循环周期。 forEach 与 for/of
【发布时间】:2021-12-05 01:01:10
【问题描述】:

是否有人注意到循环构造 forEach 和 for/of 在“迭代期间添加”项上的行为? ForEach 忽略了数组中有新添加的项目这一事实,并且 for/of 动态地改变迭代器并继续运行,直到数组中没有元素为止。这种现象的原因是什么,使用智能词?在 stackoverflow 上的第一篇文章,所以不判断解释是否简单......谢谢

let my_array1 = [1,2,3]
let my_array2 = ["a", "b", "c"]

//extra iteration cycles were not dynamically added. Loop ends after pre-defined # of cycles.
my_array1.forEach((value, index, the_array) => {
  if (value == 3){
    // my_array1.push(3)
    the_array.push(3)  // works like so as well
  }
})

console.log(`my_array1 after iteration ${my_array1}`)

//extra iteration cycles WERE dynamically added. Infinite loop!!!
for (let value of my_array2){
  if (value == "c"){
    my_array2.push("c")
  }
}

console.log(`my_array2 after iteration ${my_array2}`)

【问题讨论】:

  • 这就是它们的预期(指定)工作方式。不确定您的问题是什么?
  • 在迭代时改变一个可迭代对象通常不是一个好主意,所以它是一种边缘情况。可能是因为Array.prototype.forEach 是 ES5 的旧特性,而 for ... of 和迭代器是 ES6 - 也许发生了改变,但为了向后兼容,旧特性不会改变。

标签: javascript loops foreach


【解决方案1】:

您必须查看规范(或者,对于非本地方法,查看您使用的任何内容的文档)以了解行为是什么。比如Array.prototype.forEach,你can see

1. Let O be ? ToObject(this value).
2. Let len be ? LengthOfArrayLike(O).
3. If IsCallable(callbackfn) is false, throw a TypeError exception.
4. Let k be 0.
5. Repeat, while k < len,
  a. Let Pk be ! ToString(?(k)).
  b. Let kPresent be ? HasProperty(O, Pk).
  c. If kPresent is true, then
    i. Let kValue be ? Get(O, Pk).
    ii. Perform ? Call(callbackfn, thisArg, « kValue, ?(k), O »).
  d. Set k to k + 1.
6. Return undefined.

如您所见,它在第 2 步中在操作开始时将 k &lt; lenlen 分配给时进行迭代,因此不考虑在迭代期间添加到数组中的元素。 (不过,会看到在迭代期间更改的元素 - 因为在每次迭代中使用 Get(O, Pk) 检索值)

另一方面,for..of 用于iterables

Return ? GetIterator(exprValue, iteratorHint).

,以及迭代器is then called,直到迭代器耗尽

a. Let nextResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])

和数组迭代器包括在迭代期间添加到数组中的项目,你可以看到here。它执行

六。将 index 设置为 index + 1。

在迭代的最后,在屈服之后,在迭代的开始,查找该索引处的值。因此,在迭代器调用期间添加的元素将在迭代器的结果中看到,直到迭代器位于数组中的最后一个元素上并且没有剩余元素为止。

【讨论】:

    【解决方案2】:

    当您在数组对象上调用 .forEach 方法时,它会将循环的结尾设置为 array.length 的当前值。应该是这样的:

    const arr = [1,2,3,4]
    const end = arr.length
    for(let i = 0; i < end; i++) {
        '''code'''
    }
    

    但是,当您使用 for...of 的语法时,它与此相同:

    const arr = [1,2,3,4]
    for(let i = 0; i < arr.length; i++) {
        '''code'''
    }
    

    所以在每次迭代时它都会检查数组的长度,如果你推入数组就会改变

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2020-09-20
      • 2016-02-26
      • 2019-10-19
      • 2018-08-20
      • 1970-01-01
      相关资源
      最近更新 更多