在 JavaScript 开发中,深浅拷贝是一个绕不开的话题。无论是日常开发还是面试,拷贝对象的方式和原理都经常被问到。本文将用最简明的语言,结合实例,帮你彻底搞懂深浅拷贝的核心概念和常见实现方式,助你轻松应对各种场景!
一、什么是拷贝?为什么要拷贝?
拷贝,就是复制一个对象,让新对象和原对象"长得一模一样"。
但"复制"分为两种:浅拷贝和深拷贝。
- 浅拷贝:只复制第一层属性,如果属性是引用类型(如对象、数组),复制的是"引用地址"。
- 深拷贝:递归复制所有层级,嵌套对象也会被完整复制,新旧对象互不影响。
为什么要拷贝呢?
在 JS 中,为了避免直接修改原数据带来的副作用。这时候我们就需要复制这个对象,来操作复制的对象
二、JS 中的数据类型
理解拷贝,先要知道 JS 的数据类型:
- 基本类型:number、string、boolean、null、undefined、symbol、bigint(存储在栈内存)
- 引用类型:object、array、function、date、regexp 等(存储在堆内存)
基本类型直接存值,引用类型存的是"地址"。
三、浅拷贝:复制表面,引用共享
1. 常见实现方式
Object.assign({}, obj)
- 数组解构
[...arr]
arr.slice()
[].concat(arr)
Object.create(obj)
2. 例子说明
假设有如下对象:
js
const obj1 = {
name: "小华",
info: { age: 18 }
};
const obj2 = Object.assign({}, obj1);
obj2.name = "小鱼";
obj2.info.age = 20;
console.log(obj1); // { name: "小华", info: { age: 20 } }
解释 :
name
是基本类型,修改 obj2.name
不影响 obj1
。
info
是对象,浅拷贝只复制了引用,obj2.info.age
改变会影响 obj1.info.age
。
3. 适用场景
- 只需要复制一层属性
- 不关心嵌套对象是否联动
四、深拷贝:彻底分离,互不影响
1. 常见实现方式
JSON.parse(JSON.stringify(obj))
简单粗暴,但有缺陷:不能识别 bigin(会报错),不能拷贝function
、symbol
、undefined
,也无法处理循环引用。structuredClone(obj)
新标准,支持更多类型,但兼容性有限。- 手写递归深拷贝(见下文)
2. 例子说明(JSON.parse(JSON.stringify(obj)))
js
const obj1 = {
name: "小华",
info: { age: 18 }
};
const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.info.age = 20;
console.log(obj1); //
解释 :
obj2
完全独立,修改嵌套属性不会影响 obj1
。
3. 手写深拷贝(递归拷贝)
实现如下:
js
function deepCopy(obj) {
let newObj = {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 先判断 obj[key] 值的类型
if (typeof obj[key] === 'object' && obj[key] !== null) { // 如果是对象
newObj[key] = deepCopy(obj[key])
} else { // 如果不是对象
newObj[key] = obj[key]
}
}
}
return newObj
}
用法举例:
js
const arr1 = [1, 2, { a: 3 }];
const arr2 = deepClone(arr1);
arr2[2].a = 100;
console.log(arr1); // [1, 2, { a: 3 }]
改变了 arr2 中 {a: 3} 的值,但是原数组 arr1 的值不变。
五、常见误区与注意点
- 浅拷贝只复制一层,嵌套对象还是"共用"。
- 深拷贝要递归,但要注意循环引用、特殊类型(如 Date、函数等)。
JSON.parse(JSON.stringify(obj))
不能拷贝function
、undefined
、symbol
,也会丢失特殊对象。structuredClone
支持更全,但老浏览器不兼容。
六、总结
- 浅拷贝 :只复制一层,嵌套对象共用引用。常用
Object.assign
、展开运算符等。 - 深拷贝 :递归复制所有层级,两个对象完全独立。常用
JSON
方法、structuredClone
、手写递归。