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