• 实现深拷贝


    深拷贝

    思路:递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。
    有种特殊情况需注意就是对象存在循环引用的情况,即对象的属性直接的引用了自身的情况,解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。

    function deepClone(obj, hash = new WeakMap()) {
      if (obj === null) return obj;
      if (obj instanceof Date) return new Date(obj);
      if (obj instanceof RegExp) return new RegExp(obj);
    
      // 排除掉非数组和对象类型,函数类型也是直接返回即可
      if (typeof obj !== "object") return obj;
    
      // 处理循环引用问题,如果已经存在,则将存在的返回
      if (hash.get(obj)) return hash.get(obj);
    
      // 简单来说 new xxx.constructor 可以拿到obj的类型
      // 复杂来说 使用了原对象的构造方法,所以它可以保留对象原型上的数据,如果直接使用普通的{},那么原型必然是丢失了的。
      let cloneObj = new obj.constructor();
    
      hash.set(obj, cloneObj);
      // 拿到待拷贝对象的key,进行递归拷贝
      for (let key in obj) {
        // for in 循环同样在查找对象属性时遍历原型链上的所有属性,
        // 使用 hasOwnProperty 方法, 这将会避免原型对象扩展带来的干扰
        // hasOwnProperty 可以用来排除原型链上的属性
        // if (obj.hasOwnProperty(key)) {
        //   cloneObj[key] = deepClone(obj[key], hash);
        // }
    
        // 又或是使用其他方法循环来
        const isArray = Array.isArray(obj)
        const keys = isArray? obj : Object.keys(obj) 
        let i = 0;
        while(i <= keys.length-1) {
          cloneObj[keys[i]] = deepClone(obj[keys[i]], hash);
          i++;
        }
    
        // 对象
      }
    
      return cloneObj;
    
    }
    // 原型上的方法并不喜欢被拷贝下来
    Object.prototype.bar = {a:'test'}
    let obj = { name: 1, address: { x: 100 } };
    obj.o = obj; // 对象存在循环引用的情况
    let d = deepClone(obj);
    obj.address.x = 200;
    
    console.log(d);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    function deepClone(obj, hash = new WeakMap()) {
      if (obj === null) return obj;
      if (obj instanceof Date) return new Date(obj);
      if (obj instanceof RegExp) return new RegExp(obj);
      if (typeof obj !== "object") return obj;
      if (hash.get(obj)) return hash.get(obj);
      let cloneObj = new obj.constructor();
    
      hash.set(obj, cloneObj);
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          cloneObj[key] = deepClone(obj[key], hash);
        }
      }
      return cloneObj;
    }
    Object.prototype.bar = {a:'test'}
    let obj = { name: 1, address: { x: 100 } };
    obj.o = obj;
    let d = deepClone(obj);
    obj.address.x = 200;
    console.log(d);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    声明

  • 相关阅读:
    【Java 进阶篇】深入了解 Bootstrap 组件
    第三阶段第一章——PySpark实战
    双馈风电机组备用容量控制策略研究
    国际高性能计算和人工智能咨询委员会举办的第十届亚太区RDMA 编程赛结果出炉
    [矩阵的乘法运算] m*M = c
    在C#中使用Halcon开发视觉检测程序
    PyTorch 之 Dataset 类入门学习
    基于Java毕业设计弹幕视频网站源码+系统+mysql+lw文档+部署软件
    Shell test 命令
    《最新出炉》系列初窥篇-Python+Playwright自动化测试-37-如何截图-上篇
  • 原文地址:https://blog.csdn.net/qq_45934504/article/details/126929028