对象的浅拷贝和深拷贝

前言

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

一、浅拷贝

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);
posted @ 2020-06-13 15:24  见嘉于世  阅读(261)  评论(0编辑  收藏  举报