# 深拷贝对象
第一种: JSON.parse(JSON.stringify(obj))
const obj = {
a: {
b: 1,
c: {
d: 2
}
}
}
const deepObj = JSON.parse(JSON.stringify(obj))
deepObj.a.b = 3
console.log(obj.a.b) // 1
console.log(deepObj.a.b) // 3
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
第二种: deepClone
, 就是将以下类型进行复制, 基本类型可直接赋值, 但是以下类型需要特殊处理:
date
,regexp
,function
,symbol
,map
,set
,object
,array
点击查看代码
function getType(target) {
return Object.prototype.toString
.call(target)
.slice(8, -1)
.toLowerCase();
}
/**
* 深复制
* @param {object} obj
* @param {object} clonedObj
* @returns {object}
*/
const deepClone = (obj, clonedObj = new WeakMap()) => {
if (obj === null || typeof obj !== 'object') return obj
if (clonedObj.has(obj)) {
return clonedObj.get(obj)
}
const type = getType(obj)
let clone;
if (type === 'date') {
clone = new Date(obj.getTime())
} else if (type === 'regexp') {
clone = new RegExp(obj)
} else if (type === 'function') {
clone = function() {
return obj.apply(this, arguments)
}
} else if (type === 'symbol') {
clone = Object(Symbol.prototype.valueOf.call(obj))
} else if (type === 'map') {
clone = new Map()
for (const [key, value] of obj) {
clone.set(deepClone(key, clonedObj), deepClone(value, clonedObj))
}
} else if (type === 'set') {
clone = new Set()
for (const value of obj) {
clone.add(deepClone(value, clonedObj))
}
} else if (type === 'object' || type === 'array') {
clone = new obj.constructor()
clonedObj.set(obj, clone)
// fix: Reflect.ownKeys 可以遍历拿到 symbol 的 key
// refs: https://es6.ruanyifeng.com/#docs/symbol#%E5%B1%9E%E6%80%A7%E5%90%8D%E7%9A%84%E9%81%8D%E5%8E%86
const keys = type === 'array' ? undefined : Reflect.ownKeys(obj)
const ret = keys || obj
ret.forEach((value, key) => {
if (keys) {
key = value
}
clone[key] = deepClone(obj[key], clonedObj)
})
}
return clone
}
// example
const obj = {
dep: {
str: '123213',
age: 12,
bool: true,
nullVal: null,
undefinedVal: undefined,
arr: [1, 2, 3],
obj: { a: 1, b: 2 },
date: new Date(),
regex: /hello/g,
},
func(x) {
console.log(12321, x)
},
num: 43,
symbol: Symbol('test'),
[Symbol('symbol1')]: 'foo',
bint: BigInt(100)
}
const clone = deepClone(obj)
console.log(clone)
// {
// dep: {
// str: "123213",
// age: 12,
// bool: true,
// nullVal: null,
// undefinedVal: undefined,
// arr: [
// 1,
// 2,
// 3,
// ],
// obj: {
// a: 1,
// b: 2,
// },
// date: Sat Apr 10 2023 18:10:36 GMT+0800 (中国标准时间) {},
// regex: /hello/g,
// },
// func: function(x) {
// console.log(12321, x)
// },
// num: 43,
// symbol: Symbol(test),
// Symbol('symbol1'): 'foo',
// bint: 100n,
// }
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112