深浅拷贝
xianghaifeng 2024-06-26 js 基础
# 浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
# 浅拷贝的实现
- Object.assign()
- 展开运算符
# 深拷贝
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
# 深拷贝的实现
- JSON.parse(JSON.stringify(obj))
- 递归实现
# 深拷贝的缺点
- 无法复制不可枚举的属性
- 无法复制 Symbol 类型的属性
- 无法处理循环引用
- 无法正确处理函数
# 循环引用
循环引用指的是,对象之间相互引用,形成一个无限循环。如果不知道如何处理循环引用,深拷贝方法会进入死循环。
# 循环引用处理
- 循环引用处理
- 创建一个 Map 数据结构,用来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去 Map 中找,是否已经存在。
- 存在则直接返回,不存在则继续拷贝,然后存入 Map 中。
# 循环引用处理示例
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return null;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 处理循环引用
if (hash.has(obj)) return hash.get(obj);
let cloneObj = Array.isArray(obj) ? [] : {};
// 处理 Map Set
if (obj instanceof Map) {
cloneObj = new Map();
obj.forEach((value, key) => {
cloneObj.set(key, deepClone(value, hash));
});
return cloneObj;
}
if (obj instanceof Set) {
cloneObj = new Set();
obj.forEach((value) => {
cloneObj.add(deepClone(value, hash));
});
return cloneObj;
}
// 处理对象和数组
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33