深拷贝:深拷贝是对引用类型无限层级的拷贝,深拷贝后的拷贝对象和原对象不会互相影响,基于引用类型,原始类型没有深浅拷贝这一说法。
实现方法:可以使用递归来实现无限层级拷贝。
基础版
解释一下, new target.constructor() 能走到这一步的target说明是引用类型,可以对象或者数组,constructor() 方法指向创建该实例的构造函数,这里相当于 new Object()/new Aarray() 。
function deepClone (target) {
if (target === null || typeof target !== 'object') return target
const deepCloneObj = new target.constructor()
for (let key in target) {
deepCloneObj[key] = deepClone(target[key])
}
return deepCloneObj
}
问题
基础版出现的问题就是无法解决循环引用,如下报错提示调用栈溢出!
解决循环引用
思路:通过一个数据结构保存遍历过的对象,每次递归时先检查该结构是否已经存在,若存在则 return 对应数据提前结束本轮函数调用,否则需要保存到该结构中。
function deepClone (target) {
// 空间换时间,weakmap可被垃圾回收
const hash = new WeakMap()
function _deepClone(target) {
if (target === null || typeof target !== 'object') return target
if(hash.has(target)) return hash.get(target)
const deepCloneObj = new target.constructor()
hash.set(target, deepCloneObj)
for (let key in target) {
deepCloneObj[key] = _deepClone(target[key])
}
return deepCloneObj
}
return _deepClone(target)
}