概述
- 基本类型存储在栈内存中,假如 var a = 1,如果复制var b = a;则表示也给b创建了内存空间,因此操作b时并不会影响a;
- 引用类型是将值存储在堆内存中,而将名字存在栈内存中,并且栈内存会提供一个引用的地址,指向堆内存;
- 基本类型没有深拷贝和浅拷贝的概念,这个概念只针对于Object、Array、Function等这类引用类型的数据。
- 浅拷贝只是在栈内存了拷贝了引用的地址;而深拷贝是在堆内存中开辟了。
实现深拷贝
1. 递归复制所有层级的属性
function deepClone(obj) {
let cloneRes = Array.isArray(obj) ? [] : {};
if(obj && typeof obj === 'object') {
for(let key in obj) {
if (obj[key] && typeof obj[key] === 'object') {
cloneRes[key] = deepClone(obj[key]);
} else {
cloneRes[key] = obj[key];
}
}
} else {
cloneRes = obj;
}
return cloneRes;
}
2. 利用JSON对象的parse和stringify
var arr = [1,2,[3,4]];
var arr2 = JSON.parse(JSON.stringify(arr));
!!这些不是深拷贝
1.Object.assign()
// 如果被拷贝对象只有一层属性,就是深拷贝,第二层以后就是浅拷贝
var obj = {a: 1, b: 2};
var obj2 = Object.assign({},obj);
obj2.c = 3; // obj = {a: 1, b: 2}; obj2 = {a: 1, b: 2, c:3}
var obj3 = {a: 1, b: 2, c: 3, d: {inner:90}};
var obj4 = Object.assign({}, obj3);
obj4.c = 'c';
obj4.d.inner2 = 100;
// obj3 = {a: 1, b: 2, c: 3, d: {inner:90, inner2: 100}};
// obj3 = {a: 1, b: 2, c: c, d: {inner:90, inner2: 100}};
--------------------------------------------------
Object.assign语法,可以用于合并函数:
Object.assign(target, source1,source2...); // target: 目标对象; source:源对象,返回目标对象
2.slice()
// 被拷贝数组只有一层,就是浅拷贝,第二层以后就是深拷贝
var arr = [1,2,3];
var arr2 = arr.slice();
arr2.push(4); // arr: [1,2,3]; arr2:[1,2,3,4];
var arr = [1,2,[3,4]];
var arr2 = arr.slice();
arr2[2][1] = 5;
arr2.push(6); // arr:[1,2,[3,5]]; arr2:[1,2,[3,5], 6]
3. 展开运算符
和Object一样,只有第一层是深拷贝,第二层开始就是浅拷贝
var obj5 = {...obj4};
obj5.c = 'c5';
obj5.d.inner5 = 101;
// obj4 = {a: 1, b: 2, c: "c", d: {inner:90,inner2:100,inner5:101}}
// obj5 = {a: 1, b: 2, c: "c5", d: {inner:90,inner2:100,inner5:101}}