在javascript中,对象属于引用类型,直接赋值只会复制对象的引用地址,修改新对象会影响原对象,这种拷贝方式属于浅拷贝。深拷贝则是创建一个全新的对象,完全复制原对象的所有层级属性,新对象和原对象互不影响。下面介绍几种javascript中实现深拷贝的常用方法。

使用JSON方法实现深拷贝
JSON.parse和JSON.stringify组合是最简单的深拷贝实现方式,原理是将对象转为JSON字符串,再将字符串转回对象,从而切断引用关联。
// 原对象
const originObj = {
name: 'test',
age: 20,
hobbies: ['reading', 'coding'],
info: {
city: 'Beijing'
}
};
// 使用JSON方法深拷贝
const copyObj = JSON.parse(JSON.stringify(originObj));
// 修改拷贝后的对象
copyObj.age = 25;
copyObj.hobbies.push('swimming');
copyObj.info.city = 'Shanghai';
console.log(originObj.age); // 输出20,原对象未受影响
console.log(originObj.hobbies); // 输出["reading", "coding"],原对象未受影响
console.log(originObj.info.city); // 输出Beijing,原对象未受影响
这种方法的优点是代码简洁,不需要额外逻辑。但存在明显限制:无法拷贝函数、undefined、Symbol类型的值,Date对象会被转为字符串,RegExp、Error对象拷贝后会变成空对象,也不能处理对象循环引用的情况,遇到循环引用会直接报错。
递归遍历实现通用深拷贝
通过递归遍历对象的所有属性,逐层复制属性值,可以实现一个支持更多类型的深拷贝函数,还能处理循环引用问题。
// 深拷贝函数,支持处理循环引用
function deepClone(target, map = new WeakMap()) {
// 处理基本类型和函数,直接返回
if (typeof target !== 'object' || target === null) {
return target;
}
// 处理循环引用,如果已经拷贝过该对象,直接返回拷贝后的对象
if (map.has(target)) {
return map.get(target);
}
// 处理数组和对象
const result = Array.isArray(target) ? [] : {};
// 将当前对象和拷贝后的对象存入map
map.set(target, result);
// 遍历对象自身可枚举属性
for (const key in target) {
if (target.hasOwnProperty(key)) {
result[key] = deepClone(target[key], map);
}
}
return result;
}
// 测试循环引用场景
const obj1 = { a: 1 };
obj1.self = obj1; // 对象引用自身,形成循环引用
const copyObj1 = deepClone(obj1);
console.log(copyObj1.self === copyObj1); // 输出true,循环引用被正确处理
console.log(copyObj1.a); // 输出1
这个递归方法可以处理大部分常见的数据类型,也能解决循环引用问题。但如果是特殊的内置对象比如Map、Set、Date、RegExp等,还需要额外添加对应的类型判断和处理逻辑,才能完整支持所有对象的深拷贝。
使用第三方库实现深拷贝
实际开发中如果需要稳定可靠的深拷贝能力,也可以直接使用成熟的第三方库,比如lodash的cloneDeep方法,它已经处理了各种边界情况和特殊类型的拷贝问题。
// 假设已经引入lodash库,使用cloneDeep方法
const _ = require('lodash');
const originObj = {
name: 'demo',
date: new Date(),
fn: function() { console.log('test'); },
map: new Map([['key1', 'value1']])
};
const copyObj = _.cloneDeep(originObj);
console.log(copyObj.date instanceof Date); // 输出true,Date对象被正确拷贝
console.log(copyObj.map.get('key1')); // 输出value1,Map对象被正确拷贝
copyObj.fn(); // 输出test,函数被正确拷贝
lodash的cloneDeep方法经过了大量场景的测试,稳定性更好,适合在项目中对拷贝可靠性要求较高的场景使用,缺点是会增加项目的依赖体积,如果是轻量场景可以自行实现简单的深拷贝逻辑。
不同深拷贝方法的适用场景
可以根据实际需求选择对应的深拷贝方案:
- 如果拷贝的对象只包含基本类型、普通数组和普通对象,没有特殊类型和循环引用,优先使用JSON方法,代码最简单
- 如果需要处理更多数据类型和循环引用,且不想引入第三方依赖,可以实现递归深拷贝函数,按需扩展特殊类型的处理逻辑
- 如果项目本身已经使用了lodash等工具库,或者需要拷贝的对象包含复杂的内置对象类型,直接使用成熟的第三方深拷贝方法更稳妥
javascript深拷贝对象拷贝JSON_parse递归拷贝修改时间:2026-07-05 06:27:21