-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathdeepclone.js
70 lines (61 loc) · 1.65 KB
/
deepclone.js
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { isObject, isSet, isMap } from './../../shared/is';
/**
* 获取初始的 cloneTarget
* 比如数组是 new Array(),对象是 new Object,集合是 new Set()
* @param {Object} target 待拷贝的对象
*/
function getInit(target) {
const Constructor = target.constructor;
return new Constructor();
}
function cloneSet(target, cloneTarget, map) {
target.forEach(val => {
cloneTarget.add(deepclone(val, map));
});
return cloneTarget;
}
function cloneMap(target, cloneTarget, map) {
target.forEach((val, key) => {
cloneTarget.set(key, deepclone(val, map));
});
return cloneTarget;
}
function cloneArrAndObj(target, cloneTarget, map) {
// 遍历 target 复制属性
// Reflect.ownKeys 是 Object.getOwnPropertyNames 与 Object.getOwnPropertySymbols 之和
Reflect.ownKeys(target).forEach(key => {
if (isObject(target[key])) {
cloneTarget[key] = deepclone(target[key], map);
}
else {
Object.defineProperty(cloneTarget, key, Object.getOwnPropertyDescriptor(target, key));
}
});
return cloneTarget;
}
/**
* 深拷贝
* @param {Object} target 待拷贝的对象
*/
export default function deepclone(target, map = new WeakMap()) {
// 复制原始类型
if (!isObject(target)) {
return target;
}
const cloneTarget = getInit(target);
// 检查循环引用
if (map.has(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
// 复制 Set
if (isSet(target)) {
return cloneSet(target, cloneTarget, map);
}
// 复制 Map
if (isMap(target)) {
return cloneMap(target, cloneTarget, map);
}
// 复制对象
return cloneArrAndObj(target, cloneTarget, map);
}