如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了。
此篇文章中也会简单阐述到栈堆,基本数据类型与引用数据类型,因为这些概念能更好的让你理解深拷贝与浅拷贝。
来举个浅拷贝例子:
let a = [1,2,3,4,5,6];
b =a ;
a[0]=999;
console.log(a,b)

这个控制台是不是坏掉了,明明修改了a的值,而且在给b赋值后才改变的。

那么这里,就得引入基本数据类型与引用数据类型的概念了。
面试常问,基本数据类型有哪些,number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。
引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。
这两种存储的区别:
a.基本类型--名值存储在栈内存中,例如let a=1;

当b复制a的值的时候,栈内存会新开辟一个内存

举例一个基本类型的例子:
let a =1;
b =a;
a =110;
console.log(a,b)

修改a的时候并不会影响b,因为b自己有自己的内存空间。
举了例子:爸爸给小明,小步一人一百块钱出去玩,各自花自己的谁都不影响谁,各自都有自己的零花钱。
b.引用数据类型--名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。

这里拷贝的只是a的引用地址,值的地址就是堆内存的地址。当改变任意一方的双方都会发生改变。
再看一开始的例子:
let a = [0,1,2,3,4,5];
b =a ;
a[0]=999;
console.log(a,b)
这里当a改变的时候b也发生改变,堆内存是一样的。
再举个例子:爸爸给小明,小步一共100块钱出去玩,小明和小步不管是谁花钱100块钱都会改变,这就是浅拷贝。

那,要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,岂不就达到深拷贝的效果了
网上有递归的方法,我觉得那个方法在实战的时候力不从心。下面放出我的小妙招。
function fengqingwanli(good) {
let goods =JSON.stringify(good);
copy =JSON.parse(goods);
return copy
}
let arrGood = [1,2,3,4,5,6,[7,8,9]];
let arrsGood =fengqingwanli(arrGood);
arrGood[0] =9999;
console.log(arrGood,arrsGood)
下面来解释一下吧:
首先得明白JSON.stringify()与JSON.parse()的作用,我们可以这样理解,前者能将一个对象转为json字符串(基本类型),后者能将json字符串还原成一个对象(引用类型)。
基本类型拷贝是直接在栈内存新开空间,直接复制一份名-值,两者互不影响。
而引用数据类型,比如对象,变量名在栈内存,值在堆内存,拷贝只是拷贝了堆内存提供的指向值的地址,而JSON.stringify()巧就巧在能将一个对象转换成字符串,也就是基本类型,那这里的原理就是先利用JSON.stringify()将对象转变成基本数据类型,然后使用了基本类型的拷贝方式,再利用JSON.parse()将这个字符串还原成一个对象,达到了深拷贝的目的。
JSON.stringify()对对象的转换,避开了只拷贝地址指向,无法直接拷贝值本身的问题,不知道这样说能否理解。