面试之手写ES6深拷贝

397 阅读1分钟

面试之手写深拷贝

前言

作为一位正在准备跳槽的程序员,我们来手写一下深拷贝,深拷贝是面试的经典问题,我们来实现一下深拷贝,记录生活记录美~

深拷贝

首先让我们来试一下标准版

const deepClone =  function (target, map = new WeakMap()) {
	// 检查是否存在循环引用,没处理的话,遇到这种情况很容易爆栈
    // 使用WeakMap,是为了让对象处于弱引用,直接被垃圾回收
	if(map.has(target)) return map.get(target)
	// 首先判断是否是一个数组还是对象分别处理
    let cloneTarget = Array.isArray(target)?[]:{};
    // 检查是下面的哪种类型,我们可以通过对象的构造重新创建
    let type = [RegExp,Date, Map, Set, WeakMap, WeakSet]
    if(type.includes(target.constructor)) return new target.constructor(target)
    // 将对象缓存到map中,解决循环引用
	map.set(target, cloneTarget)
    // Reflect.ownKeys方法可以将对象上面的所有键都取出来,包括Symbol
    for(const key of Reflect.ownKeys(target)) {
      cloneTarget[key] = (typeof target[key] === 'object' && target[key] !== null)
      	// 每次遍历需要将map传入
        ? deepClone(target[key],map) : target[key]
    }
    return cloneTarget
}

继续让深入完整版


const deepClone = function(target, map=new WeakMap()) {
  if(map.has(target)) return map.get(target)
  let type = [Date, RegExp, Set, Map, WeakMap, WeakSet]
  if(type.includes(target.constructor)) return new target.constructor(target)
  
  let allDes = Object.getOwnPropertyDescriptors(target)
  let cloneTarget = Object.create(Object.getPrototypeOf(target), allDes)
  map.set(target, cloneTarget)
  for(let key of Reflect.ownKeys(target)) {
    cloneTarget[key] = (typeof target[key] === 'object' && target[key] !== null) 
    ? deepClone(target[key], map) 
    : target[key]
  }
  return cloneTarget
}

结尾

搞懂这两个版本的深拷贝,相信大家对面试深拷贝不在话下了,喜欢的小伙伴,可以点赞喔~