手写深拷贝

34 阅读2分钟
// 用JSON
const b = JSON.parse(JSON.stringfy(a))

缺点

  1. 不能支持 Date , 正则 , undefined , 函数等
  2. 不支持引用
// 用递归去实现深拷贝
const deepClone = (a,cache) => {
  if(!cache) {
    cache = new Map()
  }
  if(a instanceof Object) {
    if(cache.get(a)) {return cache.get(a)}
    let result
    if( a instanceof Function) {
      if(a.prototype) {
        result = function (){return a.apply(this , arguments)}
      } else {
        result = (...args) => { return a.call(undefined,...args)}
      }
    } else if( a intanceof Array) {
      result = []
    } else if(a intanceof Date) {
      result = new Date(a - 0)
    } else if (a intanceof RegExp) {
      result = new RegExp(a.source , a.flags)
    } else {
      result = {}
    }
    for( let key in a) {
      if(a.hasOwnProperty(key)) {
        result[key] = deepClone(a[key],cache)
      }
    }
    return result
  } else {
    return a
  }
}

但是这个也不是百分之百的拷贝,因为对象里可能没有符合上面的条件的键值。


function deepClone(a){
  if(a instanceof Object){
    let result = undefined
    if(a instanceof Function){
      if(a.prototype){
        result = function(){return a.apply(this,args)}
      }else{ // 箭头函数
        result = (...args)=> {return a.call(undefined,...args)}
      }
    }else if(a instanceof Array){
      result = new Array()
    }else if(a instanceof Date){
      result = new Date(a-0)
    }else if(a instanceof RegExp){
      result = new RegExp(a.source,a.flags)
    }else{
      result = {}
    }
    for(let key in a){
      result[key] = deepClone(a[key])
    }
    return result
  }else{
    return a
  }
}

第一步先判断是不是object还是其他 是Object后继续缩小范围,确定是Function、array等 然后声明一个result,根据是function、array生成不同的容器 最后遍历参数,对result做递归 返回result


上面还有一个缺陷,让a.self = a 然后 const b = deepClone(a),会不断的进行clone,不断循环,也被称作环。 下一步就是检查环,当已经把a拷贝成b了,当再拷贝 a 的时候,直接返回b

let cache = new Map()
function deepClone(a){
  if(cache.get(a)){
    return cache.get(a)
  }
  if(a instanceof Object){
    let result = undefined
    if(a instanceof Function){
      if(a.prototype){
        result = function(){return a.apply(this,args)}
      }else{ // 箭头函数
        result = (...args)=> {return a.call(undefined,...args)}
      }
    }else if(a instanceof Array){
      result = new Array()
    }else if(a instanceof Date){
      result = new Date(a-0)
    }else if(a instanceof RegExp){
      result = new RegExp(a.source,a.flags)
    }else{
      result = {}
    }
    cache.set(a,result)
    for(let key in a){
      result[key] = deepClone(a[key])
    }
    return result
  }else{
    return a
  }
}

缓存不能全局,最好临时创建并递归传递


function deepClone(a){
  if(!cache){
    cache = new Map()
  }
  if(a instanceof Object){
    let result = undefined
    if(cache.get(a)){
    return cache.get(a)
 		  }
    if(a instanceof Function){
      if(a.prototype){
        result = function(){return a.apply(this,args)}
      }else{ // 箭头函数
        result = (...args)=> {return a.call(undefined,...args)}
      }
    }else if(a instanceof Array){
      result = new Array()
    }else if(a instanceof Date){
      result = new Date(a-0)
    }else if(a instanceof RegExp){
      result = new RegExp(a.source,a.flags)
    }else{
      result = {}
    }
    cache.set(a,result)
    for(let key in a){
      result[key] = deepClone(a[key])
    }
    return result
  }else{
    return a
  }
}