亲们为什么要研究深拷贝和浅拷贝呢,因为我们项目开发中有许多情况需要拷贝一个数组抑或是对象,但是单纯的靠=“赋值”并不会解决所有问题,如果遇到引用类型的对象改变新赋值的对象会造成原始对象也发生同样改变,而要去除影响就必须用到深拷贝,深拷贝,对于引用对象需要进行深拷贝才会去除影响。如果是值类型直接“=”就好。
1.引用类型 引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。new 出来的对象都是引用对象
(1)值类型:String, 数值、布尔值、null、undefined。 对于值类型一个对象一个存储位置所以会互不干扰
(2)引用类型:对象、数组、函数。对于引用类型,a=b赋值后的新对象也指向同一个存储地址所以b变化a跟随变化

而要改变这种情况需要改变b的指向,使其指向b存储位置如下图

下面是各种实例对比:
第一模块-数组:
数组浅拷贝:
a =[1,2,3];b=a;b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change b:1,2,3,change
数组深拷贝://到每一项都是值类型时可以直接赋值
a =[1,2,3];a.forEach(val => b.push(val));b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change,1,2,3,change,1,2,3,change
第二模块-对象:
1-1对象浅拷贝的代码及结果

bb改变后原数组aa也跟随变化,根本原因就是像第一张线框图描述的一样
1-2对象深拷贝代码及结果,使用es6的Object.assign()方法

深拷贝bb不会影响aa
1-3对象深拷贝使用JSON.parse(JSON.stringify(obj)),即对象序列化

1-4对象深拷贝使用es6的Object.keys(obj),Object.values(obj)分别获得键数组和值数组,再通过函数根据条件循环回调deal()得到深拷贝值:《推荐使用回调》,留下个小问题,看官们可以试着这个思路去完成数组和函数回调实现深拷贝。
可复制代码:
aa = {
key:'1',
value:'a',
children:{
key: '2',
value: 'b'
}
};
function deal(obj) {
bb = {};
let keyArr = Object.keys(obj);
let valueArr = Object.values(obj);
valueArr.forEach((val,index) => {
if(Object.prototype.toString.call(val) === "[object Object]") {
deal(val)
}else {
bb[keyArr[index]] = val
}
})
return bb
}
let BB = {}
BB=deal(aa);
BB['add']='addStr';
console.log('aa:',aa,'========','BB:',BB)
截图代码和结果:

第三模块对于对象来说可复制的深拷贝代码和结果事例如下:
实例一
aa = {
key:'1',
value:'a',
children:{
key: '2',
value: 'b'
}
};
bb=aa;bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1098:9 aa: {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object
实例二
aa = {
key:'1',
value:'a',
children:{
key: '2',
value: 'b'
}
};
bb = {}
bb=Object.assign({},aa);bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1223:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()key: "1"value: "a"__proto__: Object
实例三
aa = {
key:'1',
value:'a',
children:{
key: '2',
value: 'b'
}
};
bb = {}
bb=JSON.parse(JSON.stringify(aa));bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1653:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb
欢迎转载,转载请注明出处。欢迎大家交流学习