解决对象深拷贝问题:修改嵌套属性不影响原对象
你遇到的核心问题是浅拷贝的局限性:Object.assign()和扩展运算符(...)仅复制对象的顶层属性,对于嵌套的数组、对象这类引用类型,它们复制的是内存地址而非实际内容。这就导致修改拷贝后的嵌套属性时,原对象会同步被修改。
以下是几种可行的深拷贝解决方案:
1. 手动实现深拷贝
通过递归遍历对象的每一层属性,对引用类型进行逐层复制:
function deepClone(obj) {
// 非对象类型直接返回
if (obj === null || typeof obj !== 'object') return obj;
// 处理数组
if (Array.isArray(obj)) {
return obj.map(item => deepClone(item));
}
// 处理普通对象
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = deepClone(obj[key]);
}
}
return cloned;
}
// 测试使用
const originalObject = {
name: "John Doe",
age: 30,
arr: [{ num: 1 }]
};
const copied = deepClone(originalObject);
copied.arr[0].num = 2;
console.log(originalObject.arr[0].num); // 输出1,原对象未被修改
2. 使用JSON序列化/反序列化
这是最简便的方式,但存在局限性:无法拷贝函数、Symbol、循环引用,以及Date、RegExp这类特殊对象会被转成字符串或普通对象:
const copied = JSON.parse(JSON.stringify(originalObject));
copied.arr[0].num = 2;
console.log(originalObject.arr[0].num); // 输出1
3. 原生结构化克隆(Structured Clone)
现代浏览器和Node.js(v17+)原生支持的API,能处理更多类型(Date、RegExp、Map、Set等),但仍不支持函数:
// 浏览器环境
const copied = structuredClone(originalObject);
// Node.js环境
const { structuredClone } = require('node:util');
const copied = structuredClone(originalObject);
copied.arr[0].num = 2;
console.log(originalObject.arr[0].num); // 输出1
4. 使用第三方库(如Lodash)
如果项目已引入Lodash,直接使用成熟的深拷贝方法:
const _ = require('lodash');
const copied = _.cloneDeep(originalObject);
copied.arr[0].num = 2;
console.log(originalObject.arr[0].num); // 输出1
方法选择建议
若需自定义拷贝逻辑或无依赖场景:手动实现深拷贝
简单场景且无特殊类型:JSON序列化方案
现代环境且需支持更多类型:结构化克隆API
复杂项目或已有Lodash依赖:使用_.cloneDeep
内容的提问来源于stack exchange,提问作者ThavinV