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);
    
  • 相关阅读:
    HDU 4472 Count DP题
    HDU 1878 欧拉回路 图论
    CSUST 1503 ZZ买衣服
    HDU 2085 核反应堆
    HDU 1029 Ignatius and the Princess IV
    UVa 11462 Age Sort
    UVa 11384
    UVa 11210
    LA 3401
    解决学一会儿累了的问题
  • 原文地址:https://www.cnblogs.com/buildnewhomeland/p/13114691.html
Copyright © 2011-2022 走看看