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