神奇的JS深浅拷贝

有很多小伙伴会对深浅拷贝有疑惑,到底什么是深拷贝什么是浅拷贝呢?
在这个之前,我们要知道堆与栈分别是什么。

栈:String、Number、Boolean、Null、Underined
堆:Function、Array、Object

然后我们根据上面的理解来认知接下来的深拷贝与浅拷贝

什么是浅拷贝

两个引用类型指向同一个地址,改变一个,另一个也会随之改变
我们来看一个demo

var c = { num: 18 };
var d = c;
c.num = 20;
console.log('c:', c, 'd:', d);

我们看一下浏览器
在这里插入图片描述
上面其实理解非常简单,我声明了一个对象c,因为对象复杂数据类型,存放于堆内存的,所以在栈中留下了一个指向地址指向堆中的num=18,然后我在栈中声明了一个变量d,并将c赋值给d,c是指向堆中的num,所以,d拷贝了c的指向路径当c指向的num改变了,d也会随着改变,这就是浅拷贝

我们可以看一下这个图理解一下
在这里插入图片描述

什么是深拷贝

复制后引用类型指向一个新的内存地址,两个对象改变互不影响

我们看一下demo

var c = { num: 18 };
var d = JSON.parse(JSON.stringify(c))
c.num = 20;
console.log('c:', c, 'd:', d);

再去观察一下浏览器
在这里插入图片描述

这里我们也可以这样去理解,我们在栈中声明了一个对象c并指向于堆中的num=18。
然后再在栈中声明一个变量d,然后使用序列化与反序列化的操作,将对象c深拷贝给d
然后再去修改原来c所指向的堆中的num。这两个对象是互不干扰的,因为是深拷贝的缘故,所以这样我们就实现了对象的深拷贝与浅拷贝

我们再思考一下,如果是基础数据类型的赋值他是属于深拷贝还是浅拷贝呢?
答案是:赋值既不是深拷贝也不是浅拷贝,只是跟深拷贝是类似
在这里插入图片描述
我们简单在浏览器看一下就知道,因为这是简单数据类型,不用指向堆的地址,所以可以直接的进行赋值,所以它并不是深拷贝与浅拷贝

我们再看一下,数组的方法:concat、slice是浅拷贝还是深拷贝?
concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本

写一个demo

var arr1 = [1,2,3];
var arr2 = arr1.concat();
arr2[1] = 10;
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );

看看浏览器打印
在这里插入图片描述
通过JS的concat方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响

由于数组内部属性值为引用对象,因此使用slice和concat对对象数组的拷贝,整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值