嵌套for循环中值被覆盖问题排查求助
解决嵌套循环中对象引用导致的值覆盖问题
嘿,这问题我太熟了——你遇到的是JavaScript引用类型共享导致的经典坑!咱们一步步拆解清楚:
问题根源
我猜你大概率是直接把var1赋值给了var2的data属性,类似这样:
// 错误示例:直接赋值引用 let var1 = [{ 'name': 'name1', 'list': [{ id: 0, a: "test1" }] }]; let var2 = []; for(let i = 0; i < 3; i++){ var2.push({ index: i, data: var1 }); // 这里直接把var1的引用塞进去了 }
JavaScript里数组、对象都是引用类型,不是像字符串、数字那样的值类型。上面的代码中,所有var2[i].data指向的都是同一个var1对象。所以当你在嵌套循环里修改list.id时,其实是在修改同一个var1里的list.id,最后循环结束时,自然所有var2的data里的list.id都变成了最后一次循环的i值(也就是你看到的2)。
解决方案:给每个var2.data创建独立副本
要让每个var2[i].data都是独立的、不共享的对象,你需要对var1做深拷贝。根据你的数据结构,有几种简单的实现方式:
方法1:JSON序列化/反序列化(适合简单结构)
这是最快捷的方式,适合没有函数、Symbol等特殊类型的普通对象:
let var1 = [{ 'name': 'name1', 'list': [{ id: 0, a: "test1" }] }]; let var2 = []; // 先循环创建var2的每个元素,每个data都是var1的深拷贝 for(let i = 0; i < 3; i++){ var2.push({ index: i, data: JSON.parse(JSON.stringify(var1)) // 深拷贝var1,生成独立对象 }); } // 再嵌套循环修改对应的list.id for(let j = 0; j < var2.length; j++){ for(let k = 0; k < var2[j].data.length; k++){ var2[j].data[k].list.forEach(item => { item.id = var2[j].index; // 现在修改的是每个独立副本的id }); } } // 验证结果 console.log(var2); // 此时每个var2[j].data[0].list[0].id应该等于j(0、1、2),不会再被覆盖
方法2:手动递归深拷贝(适合复杂结构)
如果你的数据里有函数、正则等JSON无法处理的类型,可以写一个递归深拷贝函数:
function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanceof Array) return obj.map(item => deepClone(item)); if (obj instanceof Object) { const cloned = {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { cloned[key] = deepClone(obj[key]); } } return cloned; } } // 使用时把JSON.parse那行替换成: // data: deepClone(var1)
关键提醒
- 浅拷贝(比如
[...var1]或者Object.assign({}, var1))只能拷贝顶层结构,对于嵌套的list数组还是共享引用,依然会出现覆盖问题,必须用深拷贝。 - 如果用现代前端框架,也可以用框架工具函数或者第三方库(比如Lodash的
_.cloneDeep)来完成深拷贝。
内容的提问来源于stack exchange,提问作者lin
相关产品推荐
相关产品推荐

