「案例图文讲解」JavaScript 中深/浅拷贝的区别

63 阅读2分钟

“可以手写一下深拷贝跟浅拷贝吗”

想必面试的时候大家都遇到过这道题吧,那么今天我们就来讲一下这个面试高频题:深/浅拷贝。

JavaScript 的 8 中数据类型

首先,需要先了解一下 JavaScript 的 数据类型,简单数据类型和复杂数据类型:

简单数据类型:Undefined、Null、Boolean、Number、 String、 Symbol(ES6 新增)、BigInt(ES10 新增)

复杂数据类型:Object

栈 与 堆 的概念

再来,了解一下内存的概念:JavaScript 的变量都存储在内存中,而内存为变量划分了两块区域,栈区域堆区域

栈区域:容量小,速度快,就像是集装箱,先进后出,先放进去的货物最后再能取出来,简单数据类型都存储在栈区域中

堆区域:容量大,速度慢,就像是仓库,要拿着取货码去找货物,而这个取货码在集装箱里;Object 顾名思义复杂在于它的由地址和内容两部分组成,地址存储在栈区域中,内容存储在堆区域中,要读取 Object 数据就要先拿着栈里的地址去堆中找内容;

IMG_4928.JPG

深拷贝 和 浅拷贝的概念与区别:

--拷贝区域原数据均为简单数据类型原数据包含对象
浅拷贝仅拷贝栈区域中的数据改变不会使原数据一同改变[case1]改变使原数据一同改变[case2]
深拷贝栈和堆区域中的数据一同拷贝简单数据类型无深拷贝改变不会使原数据一同改变[case3]

这个区别其实很好理解,浅拷贝仅拷贝栈区域中的数据,所以当拷贝的内容包含对象时,就仅拷贝栈区域中存储对象地址的部分,没有拷贝堆区域中的内容部分,所以修改拷贝后的数据仍会使原数据一同改变;

而深拷贝会把堆中的数据也一同拷贝一份,并生成一个新的地址存储在栈中(就好比把仓库里的货物也克隆一个,并生成一个新的取货码与之对应);

接下来我们来逐个分析:

case1:浅拷贝-原数据均为简单数据类型

let a1 = [1, 2, 3];
let b1 = Array.from(a1); // 浅拷贝的方法之一
b1.push(4);
console.log(a1); // [1, 2, 3]
console.log(b1); // [1, 2, 3, 4]
IMG_4931.jpg

case2:浅拷贝-原数据包含对象

let a2 = [1, 2, { a: 3 }];
let b2 = Array.from(a2);
b2.push(4);
b2[2].a = 5;
console.log(a2); // [1, 2, { a: 5}]
console.log(b2); // [1, 2, { a: 5}, 4]

IMG_4932.jpg

case3:深拷贝-原数据包含对象

let a3 = [1, 2, { a: 3 }];
let b3 = JSON.parse( JSON.stringify(a3) ) // 实现深拷贝的一种
b3[2].a = 5;
console.log(a3); // [1, 2, { a: 3}]
console.log(b3); // [1, 2, { a: 5}]
IMG_4933.jpg

以上,便是我对深拷贝与浅拷贝的理解,若有误欢迎大佬们纠错~ 截屏2023-01-26 下午6.02.40.png