前言:
之前深浅拷贝前前后后看了好几遍查看了好多资料,还是有那么一点迷糊,直到有一次看到了同学讲的ppt让我很受启发,接着我就理出了一条比较清晰的路来去理解js的深浅拷贝。要想理解深浅拷贝首先得分清,对象赋值,浅拷贝,深拷贝之间的关系。
在这之前咱们先把准备工作做好,先去理解栈和堆的概念。
对于栈和堆的定义也比较复杂抽象,非常不好理解。在这里我就用大白话说一下我对堆和栈的理解——我们其实可以认为堆是存储数据的,而栈是存储地址的。我们可以试着想象一下这个场景,在进超市的时候要存放一些私人物品,就要到存储柜区存放物品。当我们存放的时候,会先到取票机里取一张小票,才能把物品存放到柜子里。这里栈是取票机,而小票就是地址。堆是柜子,而物品就是数据。
一、对象赋值
当我们把一个对象赋值给一个新变量的时候,赋的其实是该对象在栈中的地址,而不是堆中的数据。也就是两个对象指向同一个地址,无论哪个发生变化,都会改变地址里面的内容。因此,两个对象是联动的。
let obj = { id: 1, name: "jack", data: {content: "他们俩用一个黄色的脸盆"}};
let newObj = obj;
newObj.name = "rose";
console.log(newObj);//{ id: 1, name: "rose", data: {content: "他们俩用一个黄色的脸盆"}}
console.log(obj);//{ id: 1, name: "rose", data: {content: "他们俩用一个黄色的脸盆"}}
二、浅拷贝
重新在堆中创建内存,拷贝前后基本数据类型互不影响,但是拷贝前后对象的引用类型共享同一块内存,会互相影响。(拷贝前后,基本类型互不影响,对象互相影响)。
let obj = {
id: 0,
name: "jack",
data: { content: "他们俩用一个黄色的脸盆" },
};
//对象的浅拷贝可以用结构赋值
// let newObj = { ...obj };
//对象的浅拷贝可以用Object.assign
let newObj = Object.assign({}, obj);
newObj.id = 1;
newObj.name = "rose";
newObj.data.content = "他们俩用一个红色的脸盆洗脸";
console.log(obj); //{ id: 0, name: "jack", data: {content: "他们俩用一个红色的脸盆"}};
console.log(newObj); //{ id: 1, name: "rose", data: {content: "他们俩用一个红色的脸盆"}};
这里呢可以形象的理解为一个柜子前半格被开辟出一个新内存
三、深拷贝
从堆内存中开辟一个新的区域存放新对象,拷贝前后两个对象互不影响。
let obj = {
id: 0,
name: "jack",
data: { content: "他们俩用一个黄色的脸盆" },
};
let newObj = JSON.parse(JSON.stringify(obj));
newObj.id = 1;
newObj.name = "rose";
newObj.data.content = "rose用红色的脸盆";
console.log(obj); //{ id: 0, name: "jack", data: {content: "他们俩用一个黄色的脸盆"}};
console.log(newObj); //{ id: 1, name: "rose", data: {content: "rose用红色的脸盆"}};
这里也可以形象的理解为一个柜子被分开了两半,两个柜子互不影响。