深拷贝、浅拷贝
深浅拷贝:
内存中一共分为栈内存和堆内存两大区域,所谓深浅拷贝主要是对js引用类型数据进行拷贝一份;浅拷贝就是引用类型数据赋值之后,例obj1=obj2 如果后面的操作中修改obj1对象obj2也会改变,因为在内存中引用数据类型,名字存在栈内存中,值存在堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值,两个引用类型数据地址一样,如果其中一个发生变化另外一个会有影响;而深拷贝则不会,深拷贝是会在堆内存中重新开辟一块空间进行存放。
简单来说就是B复制了A,如果A发生了改变,如果B随之变化,那么是浅拷贝,如果B并没有发生变化,则是深拷贝。
1.如果是基本数据类型,名字和值都会储存在栈内存中
let a = 1;
let b = a; // 栈内存会开辟一个新的内存空间,此时b和a都是相互独立的
b = 2;
console.log(a); //输出a为1
console.log(b); //输出b为2
2.浅拷贝实现方式
(1)用=赋值
let a = [1, 2, 3]
let b = a;
a[0] = 0;
console.log('a', a);
console.log('b', b);
运行结果
(2)用Object.assign方法
let obj1 = {
a: 1,
b: 2
}
let obj2 = Object.assign(obj1);
obj2.a = 3;
console.log('obj1', obj1)
console.log('obj2', obj2)
运行结果
3.深拷贝实现方式
(1)JSON做字符串转换
let a = [1, 2, 3];
let b = JSON.parse(JSON.stringify(a));
b[0] = 0;
console.log("a", a);
console.log("b", b);
运行结果
(2)手动实现深拷贝
let obj1 = {
a: 1,
b: 2
}
let obj2 = {
a: obj1.a,
b: obj1.b
}
obj2.a = 3;
console.log('obj1', obj1)
console.log('obj2', obj2)
运行结果
(3)用递归去拷贝所有层级属性
const deepClone = (obj) => {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj === "object") {
for (key in obj) {
//判断obj子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
return objClone;
}
let a = [1, 2, 3];
let b = deepClone(a);
b[0] = 0;
console.log("a", a);
console.log("b", b);
运行结果
let obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
}
let obj2 = deepClone(obj1);
obj2.a = 3;
obj2.c.d = 4;
console.log("obj1", obj1)
console.log("obj2", obj2);
运行结果