使用Array destructuring交换数组元素触发无限循环,临时变量却正常的原因
数组解构交换元素引发无限循环的原因解析
问题场景
在使用数组解构语法交换数组元素时遭遇无限循环,但将A[i]存入临时变量后,交换操作就能正常执行。问题代码行如下:
[A[i], A[A[i]]] = [A[A[i]], A[i]];
完整测试代码及用例:
function swap(arr, i, j) { const temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } function sort(items, newOrder) { // reorder items inline let i = 0; while(i < items.length) { while (i !== newOrder[i]) { const temp = newOrder[i]; //[items[i], items[temp]] = [items[temp], items[i]]; [items[i], items[newOrder[i]]] = [items[newOrder[i]], items[i]]; // swap(items, i, newOrder[i]); [newOrder[i], newOrder[newOrder[i]]] = [newOrder[newOrder[i]], newOrder[i]]; // swap(newOrder, i, newOrder[i]); } i++; } } // 测试用例 const items = ['A', 'B', 'C', 'D', 'E', 'F'] const newOrder = [1, 5, 4, 3, 2, 0] sort(items, newOrder);
需求是根据newOrder中的索引值对items数组进行重排序。
根本原因
问题出在数组解构赋值的执行顺序上:
数组解构赋值并非先一次性计算右侧所有值再批量赋值,而是从左到右依次执行赋值操作。
拿你代码中newOrder的交换逻辑举例,假设当前i=0,初始newOrder[0]=1:
- 先计算右侧值:
newOrder[newOrder[0]] = newOrder[1] = 5,newOrder[0] = 1,所以右侧数组是[5, 1]。 - 开始左侧赋值:
- 第一步:把
5赋值给newOrder[0],此时newOrder[0]的值已经变成了5。 - 第二步:要给
newOrder[newOrder[i]]赋值1,但此时newOrder[i](即newOrder[0])已经是5,所以实际是给newOrder[5]赋值1——这完全偏离了原本要交换newOrder[0]和newOrder[1]的目标。
- 第一步:把
这种错误的赋值会破坏newOrder的结构,导致内层循环的判断条件i !== newOrder[i]永远无法满足,最终触发无限循环。
而用临时变量temp = newOrder[i]后,temp会固定存储交换前的newOrder[i]值,后续交换操作的目标位置newOrder[temp]不会因为newOrder[i]的改变而变化,交换逻辑完全符合预期。
修正方案
方案1:使用临时变量固定交换索引
保留你代码中已有的temp变量,替换错误的解构行:
const temp = newOrder[i]; // 正确交换items [items[i], items[temp]] = [items[temp], items[i]]; // 正确交换newOrder [newOrder[i], newOrder[temp]] = [newOrder[temp], newOrder[i]];
方案2:先缓存右侧所有值再解构
如果一定要用解构,先把需要交换的两个值提前缓存,避免赋值时的依赖问题:
const currentVal = newOrder[i]; const targetVal = newOrder[currentVal]; [newOrder[i], newOrder[currentVal]] = [targetVal, currentVal];
修正后,代码会正常完成排序,最终items会变为['B','F','E','D','C','A'],newOrder会变为[0,1,2,3,4,5],满足需求。
内容的提问来源于stack exchange,提问作者Gaurav
相关产品推荐
相关产品推荐

