为什么array.forEach(()=> {array.pop()})不会清空数组

eri*_*dal 5 javascript arrays node.js

在nodejs REPL上,我试图清理一个定义为的数组,const array = [...] 并且发现使用array.forEach(() => /pop|shift/())不起作用.在这样的表达式之后,数组仍将保留其中的值.

我很清楚更好的清理阵列的方法,比如array.splice(0),但我对这种行为很好奇,似乎反直觉,至少对我而言.

这是测试:

const a = [1, 2, 3]

a.forEach(() => {
  a.shift()
})

console.log(a) // [ 3 ]

const b = [1, 2, 3]

b.forEach(() => {
  b.pop()
})

console.log(b) // prints [ 1 ]
Run Code Online (Sandbox Code Playgroud)


笔记

  1. 起初我正在使用arr.forEach(() => arr.pop()),所以我虽然其中一个值是短路forEach但是将lambda包裹在一个体块中{ .. }也会产生相同的结果.

  2. 结果在不同的节点版本和浏览器中是一致的.所以它似乎是明确定义的行为.

  3. 剩余值的数量,仍在结果数组中的值,根据输入数组的长度而变化,似乎是 Math.floor(array.length / 2)

  4. 剩余的值总是根据使用的/pop|shift/方法排序,因此一些调用实际上是在改变输入数组.

  5. 它也通过调用返回相同的结果 Array.prototype.forEach(array, fn)

Joh*_*ohn 4

从这里查看此引用:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

如果数组现有元素的值发生更改,则传递给回调的值将是 forEach() 访问它们时的值;在访问之前被删除的元素不会被访问。

您从头开始迭代,并在每次迭代中删除最后一个元素。这意味着每次迭代都会向前移动 1,并将长度减少 1。这就是为什么你最终会进行floor(initialLength / 2)迭代。您正在修改您正在修改的同一数组forEach,如上所述,这意味着您将不会为那些pop'd 元素调用回调。