zoukankan      html  css  js  c++  java
  • 对象的浅拷贝和深拷贝

    前言

    拷贝就是复制,浅拷贝和深拷贝也就是浅复制和深复制。
    网上关于浅拷贝和深拷贝的内容有很多,原理就不再多赘述了。
    一言以蔽之,所谓浅拷贝就是一层复制,所谓深拷贝就不仅仅是一层复制,还可以多层复制
    浅拷贝去复制基本类型值是没什么问题的,但是遇到了数组、对象这些引用类型值就没辙了。
    为什么没辙了呢?因为对于这些引用类型值而言,浅拷贝的这一层复制只能复制一个引用地址
    而深拷贝则解决了这个问题,对于引用类型值,它可以多层复制,而非仅仅复制一个引用地址。
    下面是浅拷贝和深拷贝的常用方法。

    一、浅拷贝

    1. 自己肝代码

    function shadowCopy(source) {
      let target = {};
      for (let i in source) {
        if (source.hasOwnProperty(i)) {
          target[i] = source[i];
        }
      }
      return target;
    }
    

    分析:for-in循环是专门用来遍历对象的可枚举属性的,但是请注意:它会遍历整条原型链。
    所以要通过对象的实例方法hasOwnProperty(keyname)来筛选只在当前实例中的属性。
    这一步就保证了复制的纯净。

    2. Object.assign(target, s1, s2, s3...) 委派方法

    let sourceObj = {
      a: 'a',
      b: 'b'
    };
    let cloneObj = {};
    Object.assign(cloneObj, sourceObj);
    

    注意:这个方法会返回一个新对象。而且如果有重复属性,那么后一个对象会覆盖前一个对象的重复属性。

    3. ES6对象三点运算符

    let sourceObj = {
      a: 'a',
      b: 'b'
    };
    let cloneObj = {...sourceObj}; 
    

    4. JSON.parse(JSON.stringify(sourceObj))

    let sourceObj = {
      a: 'a',
      b: 'b'
    };
    let cloneObj = JSON.parse(JSON.stringify(sourceObj));
    

    5. lodash库中的_.clone(sourceObj)

    先引入lodash库,随便找个CDN:

    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.core.min.js"></script>
    

    使用:

    let sourceObj = {
      a: 'a',
      b: 'b'
    };
    let cloneObj = _.clone(sourceObj);
    

    6. Jquery中的$.extend(ifDeep, target, s1, s2, s3, ...)

    引入jq库:

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    

    使用:

    let sourceObj = {
      a: 'a',
      b: 'b'
    };
    let cloneObj = $.extend(false, {}, sourceObj);
    

    7. 数组的浅拷贝

    (1) Array#slice()
    (2) Array#concat()
    (3) [...sourceArr]
    (4) Array.from(sourceArr)
    说明:#表示实例,Array#slice()就是数组实例的方法。

    二、深拷贝

    1. 自己肝代码

    function deepCopy(source) {
      let target = Array.isArray(source) ? [] : {};
      for(let key in source) {
        if(source.hasOwnProperty(key)) {
          if(typeof source[key] === 'object') {
            target[key] = deepCopy(source[key]);
          }else {
            target[key] = source[key];
          }
        }
      }
      return target;
    }
    

    分析:对于引用类型值,无非是数组和对象,所以事先要对源对象进行一个检查,这里直接用Array.isArray()。
    然后进行一层一层的判断,如果当前一层是基本类型值那么直接复制就行了,如果是对象的话,那就做一个递归即可。
    把属性值当做一个源对象去递归返回的对象再赋值给当前的键。
    如此反复,化繁为简,攻克多层对象,这就是一个能够想得通的解决思路。

    2. lodash库中的_.cloneDeep(sourceObj)

    let sourceObj = {
      a: 1,
      b: 2,
      arr: [4,5,6],
      obj: {
        a: 7,
        b: [8,9,10],
        c: {
          c1: 'c1',
          c2: 'c2',
          c3: 'c3'
        },
      },
    };
    let cloneObj = _.cloneDeep(sourceObj);
    

    3. Jquery中的$.extend(isDeep, target, s1, s2, s3, ...)

    let cloneObj = $.extend(true, {}, sourceObj);
    
  • 相关阅读:
    从0开始学FreeRTOS-(创建任务)-2
    从0开始学FreeRTOS-1
    linux(ubuntu)系统mysql-5.7 修改字符集
    腾讯云服务器简单环境配置
    linux系统ubuntu18.04安装mysql(5.7)
    ubuntu18.04从零开始配置环境(jdk+tomcat+idea)到使用idea开发web应用和servlet
    Eclipse为工具包关联源码(本例工具包为dom4j-1.6.1)
    关于c#(vs)dategridview控件继承不能修改的问题
    C语言写单链表的创建、释放、追加(即总是在最后的位置增加节点)
    c++邻接表存储图(无向),并用广度优先和深度优先遍历(实验)
  • 原文地址:https://www.cnblogs.com/buildnewhomeland/p/13114691.html
Copyright © 2011-2022 走看看