简单实现js 拷贝

104 阅读1分钟
  • 浅拷贝

const shallowClone = target => {
  if (typeof target === 'object' && target != null) {
    const cloneTarget = Array.isArray(target) ? [] : {}
    for (let targetKey in target) {
      if (target.hasOwnProperty(targetKey)) {
        cloneTarget[targetKey] = target[targetKey]
      }
    }
    return cloneTarget
  } else {
    return target
  }
}
  • 深拷贝
/**
* 缺点
* 这个深拷贝函数并不能复制不可枚举的属性以及Symbol类型
* 这种方法只是针对普通的引用类型的值做递归复制
* 对象的属性里面成环,循环引用没有解决
* @param obj
* @returns {{}}
*/
function deepclone(obj) {
 let cloneObj = {}
 for (let key in obj) {
   if (typeof obj[key] === 'object') {
     cloneObj[key] = deepclone(obj[key])
   } else {
     cloneObj[key] = obj[key]
   }
 }
 return cloneObj
}
  • 改进版

/**
 * 1.针对能够遍历对象的不可枚举属性以及Symbol类型
 * 我们可以使用Reflect。ownKeys方法
 * 2.当参数为Date regExp类型则生成一个新的实例返回
 * 3.利用Object的getOwnPropertyDescriptors方法可以获得对象的所有属性,以及对应的特性,顺便结合Object的create方法创建
 * 一个新对象,并继承传入原对象的原型链
 * 4.利用WeakMap 类型作为Hash表,因为Weakmap 是弱引用类型,可以有效防止内存泄漏,作为检测循坏引用很有帮助,如果存在循环,则引用直接返回
 * WeakMap 存储的值
 */
const deepClone2 = function(obj, hash = new WeakMap()) {
  if (obj.constructor === Date) {
    return new Date(obj)
  }
  if (obj.constructor === RegExp) {
    return new RegExp(obj)
  }
  if (hash.has(obj)) return hash.get(obj)
  let allDesc = Object.getOwnPropertyDescriptor(obj)
  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)
  //继承原型链
  hash.set(obj, cloneObj)
  for (let key of Reflect.ownKeys(obj)) {
    cloneObj[key] =
      isComplexDataType(obj[key]) && typeof obj[key] === 'function' ? deepClone2(obj[key], hash) : obj[key]
  }
  return cloneObj
}
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && obj != null