JavaScript浅拷贝和深拷贝的区别
在 JavaScript 中,浅拷贝和深拷贝是两种不同的对象复制方式,主要区别在于对嵌套对象的处理。以下是它们的详细对比:
1. 浅拷贝(Shallow Copy)
-
定义:
- 浅拷贝只复制对象的第一层属性,如果属性是引用类型(如对象、数组),则复制其引用,而不是实际的值。
-
特点:
-
嵌套对象与原对象共享同一引用。
-
修改嵌套对象会影响原对象。
-
-
实现方式:
-
扩展运算符:
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
Object.assign:
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);
- 数组的
slice或concat:
const arr = [1, 2, { a: 3 }];
const shallowCopy = arr.slice();
2. 深拷贝(Deep Copy)
-
定义:
- 深拷贝会递归复制对象的所有层级,包括嵌套对象和数组,生成一个完全独立的新对象。
-
特点:
-
嵌套对象与原对象不共享引用。
-
修改嵌套对象不会影响原对象。
-
-
实现方式:
-
JSON.parse(JSON.stringify(obj)):
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
-
局限性:
-
无法复制函数、
undefined、Symbol和循环引用。 -
递归实现:
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const obj = { a: 1, b: { c: 2 } };
const deepCopy = deepCopy(obj);
-
使用库函数:
-
使用
lodash的cloneDeep方法:
const _ = require('lodash');
const obj = { a: 1, b: { c: 2 } };
const deepCopy = _.cloneDeep(obj);
3. 示例对比
- 浅拷贝:
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 3;
console.log(obj.b.c); // 输出: 3(原对象被修改)
- 深拷贝:
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 3;
console.log(obj.b.c); // 输出: 2(原对象未被修改)
总结
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制层级 | 只复制第一层属性 | 递归复制所有层级 |
| 嵌套对象 | 共享引用,修改会影响原对象 | 独立引用,修改不会影响原对象 |
| 实现方式 | 扩展运算符、Object.assign、slice | JSON.parse(JSON.stringify)、递归、库函数 |
| 适用场景 | 简单对象复制 | 复杂对象复制,需要完全独立的对象 |
根据具体需求选择合适的拷贝方式,可以避免意外的数据修改问题。
更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github