深克隆和浅复制的基本定义
浅复制(浅克隆):直接将存储在栈中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址
深复制(深克隆):就是把数据赋值给对应的变量,从而产生一个与源数据不相干的新数据(数据地址已变化)。深拷贝,是拷贝对象各个层级的属性。
demo1-基本数据类型的赋值(以String为例)
let a = "hello world";
let b = a;
alert( b ); // 'hello world'
a = "changed";
alert( b ); // 'hello world'
// 在这段代码中,把a赋值给b,当a的值发生变化时,并不影响b
demo2-引用数据类型的赋值(以Array为例)
let arr1 = [1, 2, 3, 4];
let arr2 = arr1;
console.log( arr2 ); // [10, 2, 3, 4]
arr1[0] = 10;
console.log( arr2 ); // [10, 2, 3, 4]
// 在这段代码中,把arr1赋值给arr2,当arr1的值改变时,arr2对应的值也会改变
对以上两个例子的分析
- 对于基本数据类型而言,把a的值赋值给b后,a的修改,不会影响到b。
- 对于引用数据类型而言,把arr1赋值给arr2后,arr1的修改,会影响到arr2对应的值
- 基本数据类型是直接存储在栈内存中的,而引用数据类型,则仅仅是把地址存储在栈内存中,真正的数据是存储在堆内存中的,赋值操作时,仅仅把地址进行了赋值。
实现深克隆的方式
方法一: 递归
function deepClone( obj ){
let objClone = Array.isArray(obj) ? [] : {};
if( obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,[2, 3],4],
b=deepClone(a);
a[2][0]=10;
console.log(a,b);
方法二: JSON.stringify 和 JSON.parse
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
方法三: jQuery中的 $.extend
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
let a=[0,1,[2,3],4],
b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);