• JS 深拷贝 VS 浅拷贝


    复习到深浅拷贝问题,简单Mark一下实现方法。

    ## 写在前面

    首先我们得清楚基本概念。拷贝(Copy)即复制。

    浅拷贝:创建一个新对象,保存原始对象属性值精准拷贝。如果属性是基本类型,拷贝的是基本类型的值,如果属性是引用类型,拷贝的是内存地址,并不会占用新的内存,这种情况下如果其中一个对象改变了这个地址,会影响到另一个对象。浅拷贝只复制指向某个对象的指针,而不复制对象本身。**新旧对象共享同一块内存**。

    深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,增加了内存,且修改新对象不会影响原对象。**新对象与原对象不共享内存**。

    ## 赋值和深/浅拷贝的区别(针对引用类型)

    赋值:把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。

    浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。

    深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,前后的两个对象互不影响。

    ## 浅拷贝的实现方案

    ### 0x01 Object.assign()
    把任意多个源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

    let obj2 = Object.assign({}, obj1)

    ### 0x02 函数库lodash的_.clone方法

    var _ = require('lodash');
    
    var obj2 = _.clone(obj1);

    ### 0x03 展开运算符
    同object.assign()功能相同

    let obj2 = {...obj1}

    ### 0x04 Array.prototype.concat()

    let arr2 = arr1.concat()

    ### 0x05 Array.prototype.slice()

    let arr2 = arr1.slice()

    ## 深拷贝的实现方案

    ### 0x01 JSON.parse()和JSON.stringify()

    let arr2 = JSON.parse(JSON.stringify(arr1));

    缺点是不能处理函数和正则

    ### 0x02 函数库lodash的_.cloneDeep方法

    var _ = require('lodash');
    
    var obj2 = _.cloneDeep(obj1);

    ### 0x03 jQuery.extend()方法

    $.extend(deepCopy,target,obj1,[objN]) // 第一个参数为true就是深拷贝

    ### 0x04 手写递归实现
    解决循环引用的问题

    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();
      // 找到的是所属类原型上的constructor,而原型上的constructor指向的是当前类本身
      hash.set(obj. cloneObj);
      for(let key in obj) {
        if(obj.hasOwnProperty(key)) {
          cloneObj[key] = deepClone(obj[key], hash)
        }
      }
      return cloneObj;
    }
  • 相关阅读:
    深圳的2022
    Erlang port communicate with python
    Google v8实现类似nodejs的import加载模块
    手撕某解析网站,获取真实播放地址(保姆级讲解)(转)
    存储过程中组建集合
    svn cleanup 系统找不到指定路径_SVN:cleanup failed to process the following paths 错误
    安装Android Studio时,没有sdk列表
    html 打印时     空格不等于一个汉字问题
    使用layui出现Uncaught ReferenceError: layui is not defined
    OKR基础知识(三)
  • 原文地址:https://www.cnblogs.com/lynn-z/p/13662707.html
Copyright © 2020-2023  润新知