JavaScript数组克隆问题:修改克隆数组时原数组同步变更
JavaScript数组克隆后修改对象导致原数组变化的问题解决
你遇到的问题是:用扩展运算符克隆数组后,修改克隆数组中的对象属性,原数组也跟着发生了变化。这是因为你用的是浅拷贝,并没有真正复制数组里的对象。
你的示例代码
a = []; a[0] = {}; a[0].team = "Arsenal"; a[1] = {}; a[1].team = "Chelsea"; a[2] = {}; a[2].team = "West Ham"; function change_team(d, club){ d[1].team = club; return d; }; b = [...a]; // 克隆数组a change_team(b, "spurs"); // 期望输出:Arsenal, Chelsea, West Ham; for(n=0; n<a.length; n++){ console.log(n+"] "+a[n].team); }; // 期望输出:Arsenal, Spurs, West Ham; for(n=0; n<a.length; n++){ console.log(n+"] "+b[n].team); };
问题原因
扩展运算符[...a]属于浅拷贝:它只会复制数组本身的结构,但数组里的每个元素都是对象的引用。也就是说,a[1]和b[1]指向的是同一个内存地址里的对象,修改b[1].team本质上是修改这个共享对象的属性,所以原数组a里的对应值也会跟着改变。
解决方案
要解决这个问题,需要对数组进行深拷贝,也就是连数组里的对象也一起复制一份新的。
方法1:使用structuredClone(推荐,现代环境支持)
structuredClone是浏览器和Node.js都支持的原生深拷贝方法,能处理大多数数据类型:
b = structuredClone(a); // 深拷贝数组a change_team(b, "spurs");
方法2:使用JSON序列化(适合无特殊数据的场景)
如果数组里没有函数、undefined、循环引用这类JSON不支持的内容,可以用这种方法:
b = JSON.parse(JSON.stringify(a)); // 深拷贝数组a change_team(b, "spurs");
方法3:手动遍历克隆每个对象
如果需要更灵活的控制,可以手动遍历数组,逐个克隆对象:
// 克隆数组并逐个复制对象 b = a.map(item => ({...item})); change_team(b, "spurs");
用以上任意一种方法替换原来的b = [...a],修改克隆数组里的对象属性时,原数组就不会再被影响了。
内容的提问来源于stack exchange,提问作者Powl_London
相关产品推荐
相关产品推荐

