这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战
三、实现深浅拷贝
前文已经介绍过实现深浅拷贝的各一个方式Object.assign({}, c)、JSON.parse(JSON.stringify(c))(乞丐版),本文也将继续实践其他种类的深浅拷贝
3.1 浅拷贝
对于浅拷贝一般都是一行代码就行了,比较实现的目的比较单纯,只需要第一层为实体复制即可,主要分为两大阵营,一类是远古时期,一类是现代文明。
远古时期
其实现在也在用,没那么老😂,只是实现方式没那么现代,代码比较长。。。
3.1.1 Array.prototype.slice() 和 Array.prototype.concat()
利用的是这两个方法返回新数组的特性进行浅拷贝数组(因为这两个方法是数组的方法😂)
let a = [[1,2],2,3,4]
let b = a.slice() // < 等-价 > let b = a.concat()
b[0][0] = 10
b[1] = 20
a、b的结果如下图,可以看出,和我前文提到的浅拷贝怪异的现象一致,第一层复制的是实体,第二层复制的是引用,所以b[1]改变时,a[1]未改变;b[0][0]改变时,a[0][0]也跟着改变,详情可看我前文详细理解深浅拷贝存在的意义!!!
3.1.2 对象浅拷贝
没有找到相关比较老的方法实现,可以使用函数循环遍历实现
function cloneObj (traget) {
let ret = {}
for (let key in target) {
ret[key] = target[key]
}
return ret
}
现代文明
主要以ES6中的两种方式可以实现,一个是Object.assign、一个是扩展运算符
3.1.3 Object.assign(target, ...sources)
let obj = {
name: 'shengjingyin',
cc: {
name:"juliya"
},
}
let newObj = Object.assign({}, obj)
obj.name = 'juliya'
obj.cc.name = 'juliya'
3.1.4 ...扩展运算符
与上面唯一的不同就是=号运算时不同,结果完全一样,这才是现代化好吗,简洁舒适通用。
let newObj = { ...obj }
//--------对于数组也是一样的-------
let oldArr = [[1,2],2,3,4]
let newArr = [ ...oldArr ]
浅拷贝介绍了远古时期和现代文明的几种方式,要我选的话我会推荐后两种,特别是扩展运算符
3.2 深拷贝
深拷贝的实现的方式也有很多种(主要思想是递归)
3.2.1 JSON.parse(JSON.stringify( target ))
let a = [[1,2],2,3,4]
let b = JSON.parse(JSON.stringify(a))
a[0][0] = 5
a[1] = 20
结果如下,多层数据均为复制实体,前后无关联
3.2.2 递归
简单版递归深拷贝,主要思路:判断值是否为对象,是对象的话需要进行递归调用,这个版本有很多种!!!
function cloneDeep1(source) {
var target = {};
for(var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (typeof source[key] === 'object') {
target[key] = cloneDeep1(source[key]); // 注意这里
} else {
target[key] = source[key];
}
}
}
return target;
}