深拷贝意义及工具函数示例

🐱 个人主页:TechCodeAI启航,公众号:SHOW科技

🙋‍♂️ 作者简介:2020参加工作,专注于前端各领域技术,共同学习共同进步,一起加油呀!

💫 优质专栏:前端主流技术分享

📢 资料领取:前端进阶资料可以找我免费领取

🔥 摸鱼学习交流:我们的宗旨是在「工作中摸鱼,摸鱼中进步」,期待大佬一起来摸鱼!

        深拷贝函数是一种用于复制一个对象的函数,不仅会复制对象本身,还会递归地复制对象内部的所有属性和子对象。这篇文章将详细解读给定的深拷贝函数。

什么是深拷贝?

深拷贝是在复制一个对象时,不仅复制对象本身,还递归地复制对象内部的所有属性和子对象。它会创建一个全新的对象,该对象与原对象相等但完全独立。

深拷贝的意义在于:

  1. 避免对象共享:深拷贝创建了一个独立的对象副本,这样修改副本不会影响原始对象。这对于需要分开操作多个相同对象的情况非常有用,同时也有助于避免错误的数据共享。

  2. 维护数据的完整性:在某些情况下,如果只进行浅拷贝(只复制对象的引用),则拷贝后的对象和原对象会共享相同的属性和子对象。这可能导致意外的修改,从而破坏数据的完整性。通过深拷贝,可以确保每个对象的属性和子对象都是独立的。

  3. 处理嵌套对象:当对象内部存在其他对象时,深拷贝可以递归地复制嵌套对象。这对于处理复杂的数据结构非常有用,可以确保所有层级的对象都被正确地复制。

  4. 简化代码逻辑:使用深拷贝可以简化代码逻辑,避免手动编写复制对象的代码。通过调用深拷贝函数,可以一次性地复制整个对象及其内部的所有内容,提高代码的可读性和可维护性。

总之,深拷贝是一种重要的操作,它保证了数据的独立性和完整性,避免了共享数据的副作用。在处理复杂对象和需要保持数据隔离的情况下,深拷贝功能非常有用。

代码部分

首先,这个深拷贝函数使用了递归的方式进行深拷贝,即当遇到对象的属性值也是对象时,会再次调用深拷贝函数来对该属性值进行深拷贝。

函数接受两个参数:要拷贝的对象(obj)和一个记录已经拷贝过的对象的映射表(map,默认为空的 WeakMap)。映射表用来避免循环引用导致的无限递归。

接下来是函数的主体部分,通过一系列条件判断来确定如何进行拷贝:

  1. 如果要拷贝的对象为 null、字符串、数字、布尔值、日期对象或正则表达式对象,直接返回该对象,因为它们是不可变的基本数据类型,不需要进行深拷贝。

  2. 如果映射表中已经存在要拷贝的对象,说明该对象已经被拷贝过了,直接从映射表中取出并返回对应的拷贝对象。

  3. 如果要拷贝的对象是 Map 类型,创建一个新的 Map 对象,并将它存入映射表中。然后,遍历原对象的每个键值对,对键和值分别进行深拷贝,并将拷贝后的键值对存入新的 Map 对象中。最后返回新的 Map 对象。

  4. 如果要拷贝的对象是 Set 类型,创建一个新的 Set 对象,并将它存入映射表中。然后,遍历原对象的每个元素,对每个元素进行深拷贝,并将拷贝后的元素添加到新的 Set 对象中。最后返回新的 Set 对象。

  5. 如果要拷贝的对象是数组,创建一个空数组,并将它存入映射表中。然后,遍历原数组的每个元素,对每个元素进行深拷贝,并将拷贝后的元素添加到新的数组中。最后返回新的数组。

  6. 如果要拷贝的对象是普通对象,创建一个空对象,并将它存入映射表中。然后,遍历原对象的每个属性,对每个属性值进行深拷贝,并将拷贝后的属性值赋给新对象的对应属性。最后返回新的对象。

/**
 * 工具函数
 */
export const
  // 实现深浅拷贝
  deepClone = (obj, map = new WeakMap()) => {

    if (obj === null || typeof obj !== "object" || obj instanceof Date || obj instanceof RegExp) {
      return obj
    }
    if (map.get(obj)) {
      return map.get(obj)
    }

    if (obj instanceof Map) {
      let newObj = new Map()
      map.set(obj, newObj)
      for (let entry of obj) {
        newObj.set(entry[0], deepClone(entry[1], map))
      }
      return newObj
    } else if (obj instanceof Set) {
      let newObj = new Set()
      map.set(obj, newObj)
      for (let val of obj) {
        newObj.add(deepClone(val, map))
      }
      return newObj
    } else if (obj instanceof Array) {
      let newObj = []
      map.set(obj, newObj)
      for (let key in obj) {
        newObj[key] = deepClone(obj[key], map)
      }
      return newObj
    } else if (obj instanceof Object) {
      let newObj = {}
      // console.log(newObj)
      map.set(obj, newObj)
      console.log(newObj)
      for (let key in obj) {
        newObj[key] = deepClone(obj[key], map)
      }
      return newObj
    }

  }

最后,这篇文章提醒读者注意两点:

  1. 深拷贝函数处理了循环引用的情况,通过使用映射表来记录已经拷贝过的对象,避免了循环引用导致的无限递归。

  2. 深拷贝函数对于 Map、Set 和数组等数据结构进行了特殊处理,确保了拷贝后的对象与原对象具有相同的数据结构。

总的来说,这个深拷贝函数是一个灵活而强大的工具函数,可以帮助开发人员在需要复制对象时进行深拷贝,并避免了一些潜在的问题。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值