什么是浅克隆和浅克隆
基本定义:
浅克隆:直接将存储在栈中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址。
深克隆:就是把数据赋值给对应的变量,从而产生一个与源数据不相干的新数据(数据地址已变化)。深拷贝,是拷贝对象各个层级的属性。
使用:
- 基本数据类型的使用:
let a = 1;
let b = a;
console.log(a); //1
a = 2;
console.log(b); //1
把 a 的值赋给 b,a的值发送变化时,b不会受到影响
- 引用数据类型的使用
let arr1 = [1,2,3,4,5];
let arr2 = arr1;
console.log(arr2); //[1,2,3,4,5]
arr1[0] = 10;
console.log(arr2); //[10,2,3,4,5]
让arr1 赋值给 arr2,当arr1里面的值发送改变使,arr2中对应的值也会改变。
在变量进行克隆时,有了一个新的地址最初的样子是一样后期原值发生变化对克隆的值不会产生影响,在引用类型中克隆的是同一个地址克隆值会随着新值一起改变。
也就是说基本数据类型是直接存储在栈内存中,而引用类型是把地址存在栈内存中,真正的数据类型存在堆内存中,赋值操作时,仅仅是将地址进行了赋值。
如何实现深克隆和浅克隆
浅克隆的实现
- Object.assign()
Object.assign()用于将所有可枚举属性的值从一个或多个源对象复制到目标对象
对于Object.assign()来说, 它拷贝的是属性值。假如源对象的属性值是另一个对象的引用,那么它也只指向那个引用。
let source = {
'name':'prop',
obj:{
'name':'objprop',
innerObj:{ num:1 }
}
};
let clone = Object.assign({}, source);
source.name = 'prop1';
source.obj.name="objprop1";
source.obj.innerObj.num=99;
console.log(clone);
/*
name: "prop"
obj:
innerObj: {num: 99}
name: "objprop1"
*/
//改变克隆目标对象的对象属性,克隆对象也随之改变,说明存在引用关系
- 解构 浅克隆
解构是ES6中对赋值运算符的一种拓展,可以很方便地在复杂对象中提取数据字段.
解构可以克隆对象深层属性,然而需要注意的是,对于复杂类型,解构克隆的依然是引用。
var source = {
a: 1,
b: function () { },
c: {
d: {
num: 2,
}
}
}
var clone = { ...source};
source.c.d.num = 6;
console.log(clonec.d.num);//6
//改变source,clone也随之改变
克隆的实现
- 递归
当递归式引用类型时,采用递归层层复制
var deepCopy = function(obj) {
if (typeof obj !== 'object') return;
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
var obj = { a:1, arr: [2,3] };
var obj1 = deepCopy(obj);
obj.arr[1] = 5;
console.log(obj1.arr[1]); //3
//obj1里面的值没有改变
- JSON.parse
var obj = { a:1, arr: [2,3] };
var obj1 = JSON.parse(JSON.stringify(obj));
obj.arr[1] = 5;
console.log(deepObj.arr[1]); //3
// 克隆对象不会随原值改变
不过这个方法存在一定的局限性,只有有Number,String,Boolean,Array,扁平对象,即那些能够被json直接表示的数据结构,才能使用