JS中for...of循环操作数组:为何两次执行结果不符预期?
for...of循环中push+shift操作导致数组结果不符预期的原因
现象对比
仅push扩展数组的情况
let arr = [1, 2, 3]; for (e of arr) { arr.push(arr[arr.length - 1] + 1); if (arr.length >= 10) break; } console.log(arr) // 输出: [1,2,3,4,5,6,7,8,9,10]
这段代码里,for...of遍历数组时,每次push新元素都会让数组长度实时增加,迭代器会持续遍历新加入的元素,直到数组长度达到10触发break,最终得到完整的1-10数组。
push+shift操作数组的情况
let arr = [1, 2, 3]; for (e of arr) { arr.push(arr[arr.length - 1] + 1); if (arr[arr.length - 1] >= 10) break; arr.shift(); } console.log(arr) // 输出: [4,5,6]
这里原本预期输出[8,9,10],但实际结果却是[4,5,6],核心原因在于for...of依赖的数组迭代器的遍历逻辑。
核心原因解析
for...of循环本质是调用数组的Symbol.iterator生成迭代器,数组的默认迭代器遵循索引递增遍历的逻辑:
- 迭代器从索引
0开始,每次调用next()就访问当前数组的arr[i],然后索引i自增1 - 当
i >= 当前数组的长度时,迭代器返回done: true,循环直接终止
结合案例2的执行流程看:
- 初始数组
[1,2,3],迭代器索引i=0,取出元素1,push后数组变为[1,2,3,4],因4<10执行shift,数组变为[2,3,4],索引i自增到1 - 当前数组
[2,3,4],索引i=1取出元素3,push后变为[2,3,4,5],5<10执行shift,数组变为[3,4,5],索引i自增到2 - 当前数组
[3,4,5],索引i=2取出元素5,push后变为[3,4,5,6],6<10执行shift,数组变为[4,5,6],索引i自增到3 - 此时数组长度是3,
i=3 >= 3,迭代器直接终止循环,根本没机会触发arr[arr.length-1]>=10的break条件,最终数组停留在[4,5,6]
而案例1中,数组长度随push持续增加,迭代器的索引i可以一直递增,直到数组长度达到10触发break,因此能得到预期结果。
内容的提问来源于stack exchange,提问作者RainClick
相关产品推荐
相关产品推荐

