目录
一、什么是拷贝
谈到拷贝的话,大家应该是不陌生的,拷贝简单来说就是复制。
复制的话,这里就得想到js的两种数据类型:
1.基本数据类型:Number、String、null、undefined、Boolean。
2.引用数据类型:Object,Array
对于基本数据类型的话,复制的是值,只有一层,叫浅拷贝,而对于引用数据类型,浅拷贝只能拷贝一层,更深层的只能拷贝地址,这就会造成修改拷贝后的值的时候,原来的数据可能也会变化,这就会破坏原数据。这就需要对数据进行深拷贝。
二、浅拷贝和深拷贝概念
浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
深拷贝拷贝多层, 每一级别数据都会拷贝
2.1 浅拷贝
代码
<script>
//浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
};
var o = {};
//1.直接赋值拷贝
// o=obj;
//2.利用for...in 拷贝
// for(var k in obj){
// // k 是属性名 obj[k] 是属性值
// o[k]=obj[k];
// }
//3.利用es6的扩展运算符将对象展开进行拷贝
// o={...obj}
//浅拷贝方法
Object.assign(o, obj)
console.log(o);
<script>
这些方法都是浅拷贝的方法。
这里我们修改o对象的属性然后输出这o对象和obj对象
可以看出,修改了o对象的name属性,obj对象的name属性没有变化,但是修改o对象中的msg对象的age属性后,obj对象中的age属性也变了,这就是因为浅拷贝只拷贝一层,对更深层的对象或数组只能拷贝地址。
2.2深拷贝
深拷贝拷贝多层,每一级数据都被拷贝。
可以利用函数的递归来实现,对每一层进行拷贝,一直到最后一层,那就是深拷贝了。
代码
<script>
var obj1 = {
id: 1,
name: 'andy',
msg: {
age: 18
},
color: ['pink', 'red']
};
var o1 = {};
//封装函数
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
//判断属性值属于那种数据类型
//1.获取属性值 oldObj[k]
var item = oldObj[k];
//2.判断这个值是否是数组
if (item instanceof Array) {
newObj[k] = [];
deepCopy(newObj[k], item)
} else if (item instanceof Object) {
//3.判断是否是对象
newObj[k]={};
deepCopy(newObj[k],item)
}else{
//4.属于简单数据类型
newObj[k]=item;
}
}
}
deepCopy(o1, obj1)
o1.msg.age=15;
console.log(obj1);
console.log(o1);
</script>
对于对象的拷贝,通过函数的递归来实现,首先判断对象的属性属于那种数据类型,
1.判断是否是数组,是的话就赋值一个空数组,然后在递归调用该方法,传入这个空数组和属性,
2.判断是否是对象,是的话就赋值一个空对象,然后在递归调用该方法,传入这个空对象和属性,
3.当属性不是数组也不是对象的时候,就是基本数据类型了,直接赋值就行了。
像这样反复递归,最后都变为简单数据类型拷贝,就完成了对象的深拷贝。
从上面代码可以看出,修改o1.msg.age的值为15之后,obj1中的值没有变化,还是为18。
这就完成了对obj1 的深拷贝,也就是说,o1 对象完全复制了obj1 对象,变成一个独立的新对象,并不是多层只复制了地址。
2.3 jQuery中的拷贝
在jQuery中也提供了一个方法可以进行对象的拷贝:$.extend 和 $.fn.extend 方法。
var obj1 = {
}
var obj2 = {
name: '1234',
yh: true,
ab: {
a: 1
}
}
//将后续参数克隆给参数1
$.extend(obj1, obj2,{oo:123})
obj1.ab.a = '我被改了'
console.log('obj1', obj1);
console.log('obj2', obj2);
可以看出,是将后面的参数都克隆到参数1上了,但是对obj1中的ab对象的a属性进行修改后,obj2的属性也被修改了,所以这是浅拷贝。
不过在这个方法的第一个参数填上 true之后就能变为深拷贝
//不加true ,浅拷贝,加上true 深拷贝
var obj1 = {
}
var obj2 = {
name: '1234',
yh: true,
ab: {
a: 1
}
}
//将后续参数克隆给参数2
$.extend(true,obj1, obj2,{oo:123})
obj1.ab.a = '我被改了'
console.log('obj1', obj1);
console.log('obj2', obj2);
现在修改obj1中的属性,不会影响到obj2的属性了,变为对obj2的深拷贝了。
三、深拷贝应用场景
在前台发请求从后台获取数据的时候,获取的一般都是json格式的对象,我们一般要对这些数据进行操作,但是这些数据可能有其他地方也需要使用,就可能会造成很多隐性问题,对数据做一次深拷贝,就能让我们更安全的操作数据了,就不会出现原数据的破坏。