一个简单的深拷贝函数

137 阅读1分钟
  1. 这是一个简单易懂的深拷贝函数,处理了一些常用的数据结构,如果有特殊的结构需要处理,可以自己添加。
const cloneDeep = (target, hashMap = new WeakMap()) => {
  // 简单判断类型
  let sType = typeof target
  // 判断基本数据类型 undefined、null、number、string、boolean、symbol、bigint
  if(target === null || sType !== 'object') {
    return target
  }
  // 判断是否为函数,不考虑函数的作用域以及 this 的绑定与原函数一致
  if(sType === 'function') {
    return new Function('return ' + target.toString())
    //return new Function('...args', `return ${ target.toString().replace(/function\s*([^)]*)\s*{|}$/g, '') }(...args)`)
  }
  // 检查是否已经克隆过该对象,处理循环引用
  if(hashMap.has(target)) {
    // 如果以及存在该对象,就返回该对象
    return hashMap.get(target)
  }
  // 判断对象的特殊类型, 普通对象、数组、Map、Set、RegExp、Date
  let dType = Object.prototype.toString.call(target).slice(8, -1)
  // 处理普通对象、数组
  if(['Array', 'Object'].includes(dType)) {
    let cloneData = dType === 'Array' ? [] : {}
    hashMap.set(target, cloneData)
    for(let key in target) {
      cloneData[key] = cloneDeep(target[key], hashMap)
    }
    return cloneData
  }
  // 处理Map
  if(dType === 'Map') {
    let cloneData = new Map()
    hashMap.set(target, cloneData)
    target.forEach((value, key) => {
      cloneData.set(cloneDeep(key, hashMap), cloneDeep(value, hashMap))
    })
    return cloneData
  }
  // 处理Set
  if(dType === 'Set') {
    let cloneData = new Set()
    hashMap.set(target, cloneData)
    target.forEach(value => {
      cloneData.add(cloneDeep(value, hashMap))
    })
    return cloneData
  }
  // 处理日期对象
  if (dType === 'Date') {
    return new Date(target)
  }
  // 处理正则对象
  if (dType === 'RegExp') {
    return new RegExp(target.source, target.flags)
  }
  // 其它不常用于深拷贝的对象就不管了,直接返回就好,如果有需要再做特殊处理
  // 例如 Error、WeakMap、WeakSet、Promise、等等对象
  return target
}