实现案例1的深拷贝:
// 成功
let date = new Date
let obj = {
name: 'liuyu',
age: 12,
car: undefined,
card: null,
str: '1212s',
str1: '1212s',
ins: {
name: 'tinatina'
},
arr: [1, 2, 1, { age: 12 }, 3],
arr1: [1, 90],
dt: date,
fucion: function (a) { },
reg: /^78/,
sym: Symbol('12')
}
obj.obj2 = obj
代码:
(function () {// 使用weakMap 解决循环引用的问题
// 成功
let date = new Date
let obj = {
name: 'liuyu',
age: 12,
car: undefined,
card: null,
str: '1212s',
str1: '1212s',
ins: {
name: 'tinatina'
},
arr: [1, 2, 1, { age: 12 }, 3],
arr1: [1, 90],
dt: date,
fucion: function (a) { },
reg: /^78/,
sym: Symbol('12')
}
obj.obj2 = obj
function deep(obj, hash = new WeakMap) {
if (typeof obj === "symbol") return Symbol(obj.description); //必须写在下一行代码的前面,否则不会执行
if (typeof obj !== "object") return obj;
if (obj === null) return obj;
if (obj instanceof RegExp || obj instanceof Date) return obj.constructor(obj)
// 不可以直接obj.constructor(),因为并不能实例化构造函数,相当于:eg:Date(),获取的是一个值,并没有开辟新的堆内存
let deepObj = new obj.constructor
// hash.has判断为什么不能放在循环里,因为剪枝了
if (hash.has(obj)) {
return hash.get(obj)
}
//set 为什么不能写在for循环里?
// 假设:hash.set(element,element)
// 1. 多次调用,2. set 必须放在deep的前面,否则会出现栈溢出,但是放在前面之后的weakMap就拿不到新的堆内存的值(也就失去了深拷贝的意义,成为了浅拷贝)
// 假设:hash.set(obj,deepObj) 可以放在循环里
//set 为什么写在循环外就可以1. 确实在deep递归的前面,后面
hash.set(obj, deepObj)
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
const element = obj[key];
deepObj[key] = deep(element, hash)
}
}
return deepObj
}
const a = deep(obj)
a.dt = '5678'
a.age = 19
a.name = '456'
a.reg = /^rtyuiop/
a.fucion = function ff(b) { let a = b }
a.arr1[0] = 111
console.log(a)
console.log(obj)
console.log(obj.sym === a.sym)
})()