javaScript实现浅拷贝和深拷贝的方法有哪些?看这一篇就够了(详细)

javaScript实现浅拷贝和深拷贝的方法有哪些?看这一篇就够了!

这篇文章主要整理区分哪些方法实现的是浅拷贝,哪些方法是实现的是深拷贝,所以对于深拷贝和浅拷贝的概念不进行过多赘述(简单描述就是深拷贝是多层拷贝,浅拷贝是一层拷贝),直接进入正题:

实现浅拷贝方法:

1. 循环遍历赋值:

这里以for循环为例:
在这里插入图片描述
循环赋值后,输出newArr数组内容跟arr一模一样,接下来我们验证一下该方法实现的是深拷贝还是浅拷贝:
在这里插入图片描述
可以看到,循环赋值结束,我明明改变的是arr数组中的对象里面a的值为4,输出的newArr数组里面的对象a的值也跟着改变了,由此可以得出结论for循环赋值方法实现的是浅拷贝。

同理for…in…/for…of…/forEach循环赋值实现的同样也都是浅拷贝,有兴趣同学的可以自己私底下试一下。

2. 数组(Array)方法:
js里面数组有很多操作方法,细心的同学可能早就注意到了,很多数组方法稍微变通一下,就可以实现拷贝功能,只是纠结拷贝模式是深拷贝还是浅拷贝,这里给大家整理了一下可以实现拷贝的数组方法。

①concat(合并数组,返回新数组):空数组和需要拷贝的数组合并,返回新数组实现拷贝;
在这里插入图片描述
②slice(返回截取指定位置的子数组):从0索引开始截取,返回全新数组实现拷贝;
在这里插入图片描述
③Array.from(ES6新增:类数组对象或者可遍历对象转换成一个真正的数组):
在这里插入图片描述④Array的遍历语法都可以实现拷贝forEach/map(使用指定函数遍历数组,返回映射新数组)/filter(使用指定函数遍历过滤数组,返回过滤结果新数组),原理相同于循环遍历法。
检验一下:
在这里插入图片描述
改变了原数组arr中对象数据a的值为5,数组方法进行拷贝的值全部跟着改变了,因此可以验证数组方法对数组进行的拷贝都是浅拷贝。
3. 对象的assign方法:
object.assign方法是用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)上,类似于数组的concat方法。因此我们可以将原对象与一个空对象进行合并,生成一些新的对象实现拷贝。
在这里插入图片描述
我们尝试修改一下obj对象里面的数组c和对象d属性看一下:
在这里插入图片描述
可以看到,修改了obj中数组和对象数据,newObj里面对应的值也发生了改变,因此也验证了利用Object.assign()方法进行的拷贝也是浅拷贝。
4. JQuery.$extend():第一个参数设置false或者不加则为浅拷贝
$.extend(true,{},a,b)
true:是否深度拷贝,不加为false,浅拷贝,加了深拷贝
{}:将合并结果保存到新对象,这样原对象将不会发生改变
a:第一个合并的对象
b:第二个合并的对象

实现深拷贝的方法:

1.循环递归:通过上面验证我们知道,普通循环赋值是为浅拷贝,追其原因是因为拷贝的过程中遇到了对象类型然后只拷贝了对象的指向。所以循环递归的原理就是循环的过程中判断值的类型,如果为对象类型,则在对象类型的数据里面进行进一步循环赋值,直到循环对象里面没有对象类型的数据为止。
在这里插入图片描述
这个递归函数的原理就是先定义一个空对象newObj用来接收复制后的实例,将newObj和需要深拷贝的对象obj传入函数deepClone,函数内部通过循环赋值的方法将obj对象的值赋值给newObj,不同的是循环赋值前先判断当前值的类型是否为数组(Array)或者对象(Object)这种引用类型的值,如果是这两种引用类型的值,递归进deepClone继续进入循环赋值,直到所有的值都是基础数据类型为止,所以,这种赋值过来后的复制对象里面全是基础数据类型的数据,不存在引用类型,从而不管如果改变原对象(obj),对新对象(newObj)都不会产生任何影响。
如图:改变原对象obj里面的数组和对象值,newObj里面对应位置的值不会产生改变,可以证明obj和newObj是完全独立的两个对象

2.JSON.parse(JSON.stringfy(X))
我们都知道,利用JSON.stringify可以将JS对象转化成JSON字符串;利用JSON.parse方法可以将JSON字符串转化成JS对象。因此我们可以试一下用JSON方法实现拷贝的效果:
在这里插入图片描述
利用JSON的方法可以看出来,修改了obj和的数组和对象值,newObj的对应位置的值没有发生改变,因此可以证明利用JSON的stringify和parse方法是可以很快捷的实现深拷贝。
细心的同学可能已经发现了,newObj里面缺少了一些东西,obj里面的undefined值在newObj里面丢失了,因此我去查了一下,看看用JSON方法还有哪些局限性,整合了网上的答案,这里整理给大家:
①如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
②如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
③JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
④如果对象中存在循环引用的情况也无法正确实现深拷贝;
⑤如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
⑥如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式;

3. JQuery.$extend():第一个参数设置true;
$.extend(true,{},a,b)
true:是否深度拷贝,不加为false,浅拷贝,加了深拷贝
{}:将合并结果保存到新对象,这样原对象将不会发生改变
a:第一个合并的对象
b:第二个合并的对象

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
浅拷贝深拷贝是在JavaScript中用于复制对象或数组的两种不同方法。其区别在于复制后的对象或数组是否与原始对象或数组共享相同的内存空间。 浅拷贝只会复制原始对象或数组中的值的引用,而不会创建新的内存空间。换句话说,浅拷贝只复制了栈内存中的数据地址。因此,当修改原始对象或数组时,复制后的对象或数组也会发生改变。这种拷贝方法有点类似于拿人手短。 深拷贝则会在内存中重新开辟一段新的存储空间,使得复制后的对象或数组指向两个不同的堆内存数据。因此,当修改原始对象或数组时,复制后的对象或数组不会受到影响。这种拷贝方法可以说是自食其力。 可以通过一些方法来区分浅拷贝深拷贝。例如,假设B复制了A,当修改A时,观察B是否会发生变化。如果B也跟着变了,那么这是浅拷贝;如果B没有变化,那么这是深拷贝。 总结一下,浅拷贝只拷贝了复杂数据类型在栈内存中的地址,而深拷贝会在堆内存中重新生成一块新的存储空间,实现完完全全的对象或数组复制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [深拷贝浅拷贝的区别(javascript篇)](https://blog.csdn.net/qq_48637854/article/details/124982976)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [js浅拷贝深拷贝的区别和实现方式](https://blog.csdn.net/weixin_30388677/article/details/100091271)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值