我需要在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))

答案 0 :(得分:3)
观察大量中间writeln
s:
forEach
循环只查看每个原始索引一次 - 因此它必须将数组的长度存储在某个临时变量中。
splice
行在同一位置插入“new”:在第一个元素之后。
只有在第4位看到“3”后才会发生这种情况。
所以在第3次迭代中,在第一次插入之后,你的数组看起来像这样:
[ 0, "new", 1, 2, 3, 4, 5, 6, 7 ]
并且forEach
迭代器位于元素4 - 再次是“3”。
..因此,原始数组长度的剩余部分会插入“new”。
forEach
循环代码的编写者必须考虑有人在幕后更改数组。一个稍微更安全的方法可能是制作原始数组的副本,但我认为这需要一个深副本(你事先不能知道这个变化有多深),这可能导致大量复制似乎是一个边缘案例。
答案 1 :(得分:3)
你得到的是预期的行为,虽然它不是一个真正的无限循环 - 它是一个非生产性的循环。
您正在当前索引之前添加元素。这使当前值移动,因此您将在每次迭代时开始获得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]
答案 2 :(得分:1)
好的,让我们按步骤进行:
你的循环正常迭代,直到元素&#34; 3&#34;
关于元素&#34; 3&#34;你的循环过去&#34;新&#34;在数组的第一个位置,如: [0,new,1,2,3,4,5,6,7],但是你的所有元素都在一个位置向右移动,所以在循环的第四个元素的下一次迭代中再次#34; 3& #34;因为它被移动了。
他重复步骤2直到最后的第8个元素,并且重复4次以及#34; new&#34;在阵列的第一个位置。 如果你想粘贴&#34; new&#34;有一次这样做:
A.forEach(function(x){
if(x == 3){A.splice(1,0,&#39; new&#39;);打破;}
})