You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Object.assign克隆对象数组的异常问题及原理问询

问题解析与解决方案

为什么修改拷贝后的数组会影响原数组?

核心原因是**Object.assign()执行的是浅拷贝**,哪怕操作的是数组也遵循这个规则:

  1. 在JavaScript中,数组本质是特殊的对象,数组的索引(比如0)就是对象的数字型属性名。
  2. 当你执行Object.assign([], original)时,它会把原数组的所有“属性”(即各个索引对应的元素值)复制到新数组中。但原数组的元素是对象引用,Object.assign()只会复制这个引用,不会复制引用指向的对象本身。
  3. 这就导致新数组copy的第一个元素和原数组original[0]指向同一个内存地址的对象。你在copy.forEach里修改obj.value,实际是直接修改了这个共享的对象,原数组自然会同步变化。

对应MDN说明的解释

MDN提到的“仅复制属性值,如果源值是对象引用,只会复制引用值”完全适用于你的场景:

  • 数组的索引属于对象属性,数组元素就是属性值;
  • 当属性值是对象引用时,Object.assign()只会复制引用,而非对象的副本,所以修改引用指向的对象会影响所有持有该引用的变量。

实现数组深拷贝的方法

如果要实现真正的深拷贝(修改拷贝后的内部对象不影响原数组),可以用以下几种方式:

方法1:JSON序列化/反序列化(简单通用)

适合大多数没有特殊类型(如函数、Symbol、循环引用)的场景:

const original = [ { value: 1 } ];
function test() {
    const copy = JSON.parse(JSON.stringify(original));
    copy.forEach(obj => obj.value = obj.value + 1);
}

console.log(original[0].value); // -> 1
test();
console.log(original[0].value); // -> 1
test();
console.log(original[0].value); // -> 1

方法2:数组map结合对象浅拷贝(适合单层对象数组)

如果数组内只有一层对象,可以用map遍历每个元素,单独拷贝对象:

const copy = original.map(obj => ({...obj}));
// 或者用Object.assign
const copy = original.map(obj => Object.assign({}, obj));

方法3:手动递归深拷贝(适合复杂场景)

如果需要处理函数、Symbol或循环引用,可以自己实现递归深拷贝逻辑,遍历每个属性并复制值,遇到对象则递归处理。

内容的提问来源于stack exchange,提问作者Khryus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:35:12