通用深拷贝

53 阅读1分钟

深拷贝:深拷贝是对引用类型无限层级的拷贝,深拷贝后的拷贝对象和原对象不会互相影响,基于引用类型,原始类型没有深浅拷贝这一说法。

实现方法:可以使用递归来实现无限层级拷贝。

基础版

解释一下, 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
}

问题

基础版出现的问题就是无法解决循环引用,如下报错提示调用栈溢出!

image.png

解决循环引用

思路:通过一个数据结构保存遍历过的对象,每次递归时先检查该结构是否已经存在,若存在则 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)
}