如何避免修改对象内部数组的对象字段时篡改原对象?
解决对象深拷贝问题:修改嵌套属性不影响原对象
你遇到的核心问题是浅拷贝的局限性: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
相关产品推荐
相关产品推荐

