浅拷贝与深拷贝

如何区分深拷贝与浅拷贝,简单点来说,就是假设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()对对象的转换,避开了只拷贝地址指向,无法直接拷贝值本身的问题,不知道这样说能否理解。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容