深拷贝和浅拷贝是针对引用类型的
浅拷贝:
简单来说就是一个对象B复制另一个对象A,当改变B对象的值是A对象的值也随之改变。
举个例子:
var obj1={a:1,b:5,c:3};
var obj2=obj1;
obj2.b=2;
console.log(obj1.b); //2
console.log(obj2.b); //2
可以看到两个对象的值都被修改了
浅拷贝:只复制指向某个对象的指针,而不复制对象本身,相当于是新建了一个对象,该对象复制了原对象的指针,新旧对象还是共用一个内存块,任何一个修改都会是使得所有对象的值被修改
应用场景:从服务器fetch到数据之后我将其存放在store中,通过props传递给界面,然后我需要对这堆数据进行修改,那涉及到的修改就一定有保存和取消,所以我们需要将这堆数据拷贝到其它地方
深拷贝:
简单来说就是一个对象B复制另一个对象A,当改变B对象的值是A对象的值不会改变。
举个例子:
var a=2;
var b=a;
b=3;
console.log(a);//2
console.log(b);//3
以上例子说明两个变量使用的是独立的数据。对于基本数据类型来说不存在深拷贝、浅拷贝。直接赋值就是深拷贝。
深拷贝:深拷贝不会拷贝引用类型的引用,拷贝的是引用类型的值,形成一个新的引用类型。新建一个一模一样的对象,该对象与原对象不共享内存,修改新对象也不会影响原对象
应用场景:当你想使用某个对象的值,在修改时不想修改原对象,那么可以用深拷贝弄一个新的内存对象。像es6的新增方法都是深拷贝,所以推荐使用es6语法
如何实现深拷贝:
①JSON.Stringify(JSON.pare()) 不支持多层引用嵌套,不支持函数Map、Sep等类型的数据
var obj1={a:1,b:5,c:3};
var obj2=JSON.Stringify(JSON.parse(obj1));
obj2.b=2;
console.log(obj1.b); //5
console.log(obj2.b); //2
②jQuery.extend()方法,第一个参数要传true
③Object.asssign(target,sourse)
var obj1={a:1,b:5,c:3};
var obj2=Object.assign({},obj1)
obj2.b=2;
console.log(obj1.b); //5
console.log(obj2.b); //2
④深拷贝函数,递归
// target 要拷贝的对象
function deepClone(target){
//定义一个拷贝对象
let result;
// 判断拷贝目标是不是Object对象
if(typeof target==='object'){
// 判断是否是数组类型
if(Array.isArray(target)){
// 定义为数组
result=[];
for(let i in target){
result.push(deepClone(target[i]));
}
}else if(target===null){
// 直接赋值
result=null;
}else if(target.constructor===RegExp){
// 直接赋值
result=target;
// 不是特殊的对象
}else{
result={};
for(let i in target){
// 递归
result[i]=deepClone(target[i]);
}
}
// 基本数据类型 直接赋值
}else{
result=target;
}
return result;
}
var obj1={
a:{z:1,c:null},
b:[1,2,3,5],
c:function(){console.log(this.a)}
}
var obj2=deepClone(obj1);
console.log(obj2);
obj2.b[0]=2;
obj2.a[0]=2;
console.log(obj1.a)
console.log(obj2.a)
console.log(obj1.b)
console.log(obj2.b)
console.log(obj2.c())