一种讨巧的深拷贝实现

/
文章热度/?
本文共计/0 字
预计阅读/0 分钟

今天见到一种很巧的deepClone的实现,之前写深拷贝代码都会写很长,而且各种判断;或者用JSON.parse(JSON.stringify(obj))的方式,但是这种方式如果有循环引用则会报错。

这段代码通过使用Message Channel巧妙地解决了循环引用的问题,实现了深拷贝。

function deepClone(obj) {
  return new Promise((resolve) => {
    const { port1, port2 } = new MessageChannel()
    port1.postMessage(obj)
    port2.onmessage = (msg) => {
      resolve(msg.data)
    }
  })
}

不过需要注意的是,该代码仍然无法克隆function,也会丢失Symbol作为key的属性。

最后附上经典的深度克隆代码:

function deepCopy(obj, cache = []) {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }
  const objType = Object.prototype.toString.call(obj).slice(8, -1)
  // 考虑 Symbol对象的copy
  if (objType === 'Symbol') {
    return Symbol(obj.description)
  }
  // 考虑 正则对象的copy
  if (objType === 'RegExp') {
    return new RegExp(obj)
  }
  // 考虑 Date 实例 copy
  if (objType === 'Date') {
    return new Date(obj)
  }
  // 考虑 Error 实例 copy
  if (objType === 'Error') {
    return new Error(obj)
  }
  const hit = cache.filter((c) => c.original === obj)[0]
  if (hit) {
    return hit.copy
  }
  const copy = Array.isArray(obj) ? [] : {}
  cache.push({ original: obj, copy })
  Object.keys(obj).forEach((key) => {
    copy[key] = this.deepCopy(obj[key], cache)
  })
  // 对key为Symbol类型的情况进行处理,拿到所有为Symbol类型的key
  const symbolKeys = Object.getOwnPropertySymbols(obj)
  // for...of遍历取出所有的key,存放到新对象中
  for (const sKey of symbolKeys) {
    copy[sKey] = deepCopy(obj[sKey], cache)
  }
  return copy
}

一种讨巧的深拷贝实现

https://blog.vidorra.life/p/2023050601

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

© 2023圈圈 本站总访问量 ???人次
Powered byHexo&Dreamland
GO GO GO GO