1.浅拷贝与深拷贝
简单来讲,浅拷贝是指向和拷贝对象相同的内存地址,因为是共用一个地址,所以当拷贝对象发生变化时,我们新的对象也会发生变化。
深拷贝的话,我们是开辟了一块新的内存地址来存放新的对象,这样两个对象是指向不同内存地址,所以对于被拷贝对象进行修改时,不会影响到拷贝的对象。
如浅拷贝:
let a=[0,1,2,3,4],
b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);

再例如**简单数组的深拷贝(没有嵌套层级)**的深拷贝


当然这里只是进行简单的复制,不算真正意义上的深拷贝。
基本数据类型的话,浅拷贝深拷贝的概念不严谨,因为如果是基本数据类型,都是存储在栈中,一旦声明就会有新的内存空间,这样看都是深拷贝,所以说基本数据类型是没有深浅拷贝的说法,深浅拷贝都是针对复杂数据类型来说的。
基本数据类型:number,string,boolean,null,undefined,symbol,BigInt七个
复杂数据类型:对象,数组,函数等
1.基本数据类型的存值–键值存在栈内存中,let a= 1;

当你b=a复制时,栈内存会新开辟一个内存,例如这样:

基本数据类型修改任何一个都对其他不影响
2.引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

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

而当我们a[0]=1时进行数组修改时,由于a与b指向的是同一个地址,所以自然b也受了影响,这就是所谓的浅拷贝了。

要是在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,就是深拷贝!

简单数组(对象)的深拷贝(无层级嵌套)
1.Object.assign()–针对对象
Object.assign是用于对象的合并,它可以将一个或多个可枚举的对象合并到一个新的对象(注意:这里如果对象有继承的属性,则不会合并过去)


对其一个属性进行改变


这里我们的obj对象只是第一层键值对,所以在这里就是进行的深拷贝,我们改变obj的name但是obj2的name没有发生变化。但是对于深层次的对象来说就不一样了。


两个都变,obj2里已经发生变化了,我们可以这样理解Object.assign()对于第一层数据进行了深拷贝,但是对于深层次的数据就进行了浅拷贝。
在这里需要注意一点,Object.assign()是合并对象的,如果是字符串,则会以有序列的对象形式拷贝到对象中

那为什么Object.assign只能实现一层的深拷贝呢;看下它的源码就理解了,它方法中写的也只是简单的赋值复制

2.扩展运算符–对象数组都可
扩展运算符将一个数组和对象转为用逗号分隔的参数序列

3.数组的concat方法–针对数组


4.数组的slice方法–针对数组


对于数组项是引用类型的数据(有层级嵌套),就无法实现深拷贝了。

真正的深拷贝(层级嵌套)
1.JSON方法
利用JSON.stringify()转化为JSON字符串,然后再转回;字符串是基本数据类型,所以这样就可以各占内存,各不影响;
这就是为什么JSON可以实现深拷贝的原因

2.函数库lodash的_.cloneDeep方法(没用过)

3.递归实现深拷贝

参考链接:https://blog.youkuaiyun.com/Deku_Ln/article/details/110628565
本文详细介绍了JavaScript中的浅拷贝和深拷贝概念,通过实例展示了两者的区别。浅拷贝仅复制对象引用,而深拷贝则创建了新的内存空间存放复制品。对于基本数据类型,没有深浅拷贝之分,而对于复杂数据类型如对象和数组,深拷贝是必要的。文中提到了Object.assign()、扩展运算符、数组的concat和slice方法实现的深拷贝局限性,并强调了JSON.stringify()和lodash.cloneDeep()以及递归方法可用于实现层级嵌套的深拷贝。
398

被折叠的 条评论
为什么被折叠?



