Skip to content

Commit e58609b

Browse files
committed
feat[ptr]: 用记忆化解决循环引用问题:如果某个对象已经拷贝过了,就直接返回之前的拷贝
1 parent 3f876e2 commit e58609b

1 file changed

Lines changed: 35 additions & 39 deletions

File tree

JS/algorithm/deepCopy.js

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,49 @@
11
// 用记忆化解决循环引用问题:如果某个对象已经拷贝过了,就直接返回之前的拷贝
22
// 映射: 原对象 -> 拷贝对象
3-
function deepCopy(from, vis = new WeakMap()) {
4-
if (vis.has(from))
5-
return vis.get(from)
6-
if (Object.prototype.toString.call(from) === '[object Object]') {
7-
const to = {}
8-
vis.set(from, to)
9-
for (const key of Object.keys(from)) {
10-
to[key] = deepCopy(from[key], vis) // 注意得用属性计算符 [] 而不是 .
11-
}
12-
return to
13-
}
14-
else if (Object.prototype.toString.call(from) === '[object Array]') {
15-
const to = []
16-
vis.set(from, to)
17-
for (const item of from) {
18-
to.push(deepCopy(item, vis))
19-
}
20-
return to
21-
}
22-
else {
3+
function deepCopy(from, memo = new WeakMap()) {
4+
if (typeof from !== 'object' || from === null) {
235
return from
246
}
25-
}
267

8+
if (memo.has(from)) {
9+
return memo.get(from)
10+
}
2711

12+
let to
2813

29-
// const vis = new Set() // 通过将访问过的对象放入到 vis 中实现记忆,防止循环引用
30-
// 不用 hash 因为正是要判断引用数据类型的引用地址
31-
function deepCopy(from, vis = new Set()) { // vis不要污染外部,并且需要保证是自己的上层而不是其他分支的上层
32-
if (vis.has(from))
33-
throw new Error('circular reference')
34-
if (Object.prototype.toString.call(from) === '[object Object]') {
35-
vis.add(from)
36-
const to = {}
37-
for (const key of Object.keys(from)) {
38-
to[key] = deepCopy(from[key], vis) // 注意得用属性计算符 [] 而不是 .
39-
}
40-
vis.delete(from) // 注意 归 后需要删除
14+
if (from instanceof Date) {
15+
to = new Date(from)
16+
}
17+
else if (from instanceof RegExp) {
18+
to = new RegExp(from)
19+
}
20+
else if (from instanceof Map) {
21+
to = new Map()
22+
memo.set(from, to)
23+
from.forEach((v, k) => {
24+
to.set(deepCopy(k, memo), deepCopy(v, memo))
25+
})
4126
return to
4227
}
43-
else if (Object.prototype.toString.call(from) === '[object Array]') {
44-
const to = []
45-
for (const item of from) {
46-
to.push(deepCopy(item, vis))
47-
}
28+
else if (from instanceof Set) {
29+
to = new Set()
30+
memo.set(from, to)
31+
from.forEach(v => {
32+
to.add(deepCopy(v, memo))
33+
})
4834
return to
4935
}
5036
else {
51-
return from
37+
to = Array.isArray(from) ? [] : {}
5238
}
39+
40+
memo.set(from, to)
41+
42+
for (const key in from) {
43+
if (from.hasOwnProperty(key)) {
44+
to[key] = deepCopy(from[key], memo) // 注意得用属性计算符 [] 而不是 .
45+
}
46+
}
47+
48+
return to
5349
}

0 commit comments

Comments
 (0)