四种深拷贝方式,看看你都知道吗?

194 阅读1分钟

介绍

大家好,深拷贝在面试中常常被问到,在此总结了四种深拷贝的方法。

第一种 structuredClone

这个是官方给出的深拷贝api,可以轻松实现深拷贝,对比JSON.parse(JSON.stringify(Object))更加安全,目前适配了大部分浏览器,mdn是这样描述的: structuredClone()  方法使用结构化克隆算法将给定的值进行深拷贝

缺点

  • 原型:无法拷贝对象的原型链。
  • 函数:无法拷贝函数。
  • 不可克隆:并没有支持所有类型的拷贝,比如 ErrorDOM节点

第二种 JSON.parse(JSON.stringify(Object))

这个方法处理简单的数据类型尚可,对于一些复杂数据类型例如Dateundefinded有坑

  • 更改数值:当有undefined类型或function类型的数据时会把key丢失掉,有NaN、Infinity和-Infinity这三种值的会序列化成null
  • 循环饮用:当遇到循环引用的情况会报错

第三种 MessageChannel

MessageChannel是可以在Web Worker中使用的。我们可以利用这个特性在两个web worker中通信。也可以去实现深拷贝, 这个方法实际是我最近新学习的一个方法,希望大家在面试中可以多一种深拷贝的方式,

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


缺点

  • 异步:这样传输会有异步的问题
  • function:传输的对象有function 会报错告诉你无法被clone

第四种 递归

这个方法简直是老生长谈没有什么好说的,具体直接上代码

/**
 * @description 普通深拷贝
 * @param {object|Array} obj
 */
const cloneDeep = (obj) => {
  const objClone = Array.isArray(obj) ? [] : {}
  for (const key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      if (obj[key] && typeof obj[key] === 'object') {
        objClone[key] = cloneDeep(obj[key])
      } else {
        objClone[key] = obj[key]
      }
    }
  }
  return objClone
}