手写js之深克隆

241 阅读1分钟

背景

前几天,写了手写js之浅克隆,反馈还行,于是趁热就出这个姐妹篇。

分析

深克隆对比浅克隆,最主要的特点,是如果目标对象是数组,或者对象,需要继续递归处理,直到处理的数据不再是普通对象,或者数组

实现

准备两个辅助方法

// 判断是否是正则
const isRegExp = (value) => Object.prototype.toString.call(value).slice(8, -1) === 'RegExp'

//判断是否是日期
const isDate = value => Object.prototype.toString.call(value).slice(8, -1) === 'Date'
function cloneDeep (value) {
  if (typeof value !== 'object') {
    return value
  }
  /* 对null的处理 */
  if (value === null) return null
  /* 对正则的处理 */
  if (isRegExp(value)) {
    return new RegExp(value)
  }
  /* 对日期的处理 */
  if (isDate(value)) {
    return new Date(value)
  }
  const res = Array.isArray(value) ? [] : {}

  const map = new Map()

  for (let key in value) {
    /* 先判断map中是否存在key, 如果存在,则直接从map从获取 */
    if (map.get(key)) {
      return map.get(key)
    }
    /* 不存在,则递归处理 */
    map.set(key, value[key])
    res[key] = cloneDeep(value[key])
    
  }

  return res
}

测试

1、测试基本数据类型
2、测试对象,数组
3、测试函数
4、测试正则
5、测试日期
6、测试循环引用

var obj = {
  a: 1,
  b: null,
  c: {
    d: 2,
    e: [1, 2, 3]
  },
  f: function() {},
  g: /123/,
  h: new Date(),
  i: {}
}

obj.i.c = obj.c

console.log(cloneDeep(obj))

const cloneObj = cloneDeep(obj)

cloneObj.c.d = 1 

console.log(obj.c.d, cloneObj.c.d);

测试结果如下:

image.png