深拷贝:拷贝出来的对象与原对象毫无关系,不会拷贝引用,会进行深层次的拷贝

一、JSON序列化

  1. const jsonString = JSON.stringify(obj)
  2. const obj1 = JSON.parse(jsonString)

缺点:

  1. 对象中函数、undefined不会被处理,默认移除
  2. Symbol作为key或value都不会被处理,默认移除
  3. 如果存在对象的循环引用则会报错
  4. 对象中NaN、infinity会被转成null
  5. new Date日期会被自动转为字符串
  6. 正则reg、Map、Set会被转成空对象{}

二、自己实现深拷贝

解决循环引用造成的问题:

  • 循环引用也就是 obj.info = obj
  • 在深拷贝时,会造成栈溢出的情况,也就是不断地递归创建新的对象
  • 那么怎么解决呢?
  • 其实在第一次进入循环的时候,已经创建过一次拷贝对象了
  • 那么直接返回原来生成的拷贝对象就可以了,没必要再创建一次
  • 在深拷贝时,其实就是 newObj.info = newObj 将newObj作为info的值就可以了
  • 用WeakMap去存放oldObj和newObj ```javascript function isObject(value) { const valueType = typeof value return value !== null && (valueType === ‘object’ || valueType === ‘function’) }

function deepClone(originValue, map = new WeakMap()) { // 利用map作为变量使得每次拿到的都是同一个map

// 判断set类型(浅拷贝) if (originValue instanceof Set) { return new Set([…originValue]) }

// 判断map类型(浅拷贝) if (originValue instanceof Map) { return new Map([…originValue]) }

// value为Symbol类型 if (typeof originValue === ‘symbol’) { return Symbol(originValue.description) }

// 判断function类型 if (typeof originValue === ‘function’) { return originValue }

// 判断object类型 if (!isObject(originValue)) { return originValue }

// 判断是否是之前已经拷贝过的对象 if (map.has(originValue)) { return map.get(originValue) }

const newObject = Array.isArray(originValue) ? [] : {} // 将原对象与拷贝对象形成映射 map.set(originValue, newObject) for (const key in originValue) { newObject[key] = deepClone(originValue[key], map) }

// Symbol作为key时进行特殊处理 const symbolKeys = Object.getOwnPropertySymbols(originValue) for (const sKey of symbolKeys) { newObject[sKey] = deepClone(originValue[sKey], map) }

return newObject } ```