前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >深拷贝和浅拷贝原来是这样?

深拷贝和浅拷贝原来是这样?

作者头像
IT人一直在路上
发布于 2019-09-16 03:32:21
发布于 2019-09-16 03:32:21
41100
代码可运行
举报
文章被收录于专栏:前端重点笔记前端重点笔记
运行总次数:0
代码可运行

为了让读者更好的理解深浅拷贝,在讲深浅拷贝之前要引入基本数据类型 , 引用数据类型 和 数据储存(栈和堆)这几个概念,如果已经理解,可直接跳过这一part。

JS数据类型

Q:前端面试常问,JS的基本数据类型有哪些呀?

A:JS数据类型分为基本数据类型和引用数据类型,详细分类如下:

Q:基本数据类型和引用数据类型的储存方式有什么不同?

A:

  • 基本数据类型:变量名和值都储存在栈内存中,例如:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var num=10;

num变量在内存中储存如下:

  • 引用数据类型:变量名储存在栈内存中,值储存在堆内存中,但是堆内存中会提供一个引用地址指向堆内存中的值,而这个地址是储存在栈内存中的,例如:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var arr=[1,2,3,4,5];

arr变量在内存中的储存如下:

对这几个概念有了初步了解之后,接下来正式开始讲深浅拷贝。

什么是浅拷贝和深拷贝

在讲两者概念之前我们先看一个需求:现在有一个对象A,需求是将A拷贝一份到B对象当中?

浅拷贝

当B拷贝了A的数据,且当B的改变会导致A的改变时,此时叫B浅拷贝了A,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//浅拷贝
var A={
 name:"martin",
 data:{num:10}
}
var B={}
var B=A;
B.name="lucy";
console.log(A.name); //lucy

A直接赋值给B后,B中name属性的改变导致了A中name属性也发生了变化。

其实是因为这种赋值方式只是将A的堆内存地址赋值给了B,A和B储存的是同一个地址,指向的是同一个内容,因此B的改变当然会引起A的改变。

浅拷贝的方式

直接赋值

第一种方式就是上面所写代码中的将对象地址直接进行赋值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var A={
 name:"martin",
 data:{num:10}
};
var B={};
B=A;
B.name="lucy";
console.log(A.name); //"lucy",A中name属性已改变

Object.assign(target,source)

这是ES6中新增的对象方法,对它不了解的见ES6对象新增方法,它可以实现第一层的“深拷贝”,但无法实现多层的深拷贝。

以当前A对象进行说明

第一层“深拷贝”:就是对于A对象下所有的属性和方法都进行了深拷贝,但是当A对象下的属性如data是对象时,它拷贝的是地址,也就是浅拷贝,这种拷贝方式还是属于浅拷贝。

多层深拷贝:能将A对象下所有的属性,及时属性是对象,也能够深拷贝出来,让A和B相互独立,这种叫才叫深拷贝。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var A={
 name:"martin",
 data:{num:10}say:function(){
 console.log("hello world") 
 }
}
var B={}
Object.assign(B,A); //将A拷贝到B
B.name="lucy";
console.log(A.name); //martin,发现A中name并没有改变
B.data.num=5;
console.log(A.data.num); //5,发现A中data的num属性改变了,说明data对象没有被深拷贝

浅拷贝总结

直接赋值:这种方式实现的就是纯粹的浅拷贝,B的任何变化都会反映在A上。

Object.assign():这种方式实现的实现的是单层“深拷贝”,但不是意义上的深拷贝,对深层还是实行的浅拷贝。

深拷贝

当B拷贝了A的数据,且当B的改变不会导致A的改变时,此时叫B深拷贝了A,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//深拷贝
var A={
 name:"martin",
 data:{num:10}say:function(){
 console.log("hello world") 
 }
} //开辟了一个新的堆内存地址,假设为placaA
var B={}; //又开辟了一个新的堆内存地址,假设为placeB
B=JSON.parse(JSON.stringfy(A));
B.name="lucy";
console.log(A.name); //martin

通过JSON对象方法实现对象的深拷贝,我们可以看到其中B.name值的改变并没有影响A.name的值,因为A和B分别指向不同的堆内存地址,因此两者互不影响。

深拷贝的方式

理解了深浅拷贝,接下来说一下深拷贝的几种方式。

首先假设一个已知的对象A,然后需要把A深拷贝到B。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var A={
 name:"martin",
 data:{num:10},
 say:function () {
 console.log("say");
 }
};
var B={};

递归赋值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function deepCopy(A,B) {
 for(item in A){
 if(typeof item=="object"){
 deepCopy(item,B[item]);
 }else{
 B[item]=A[item];
 }
 }
}
deepCopy(A,B);
B.data.num=5;
console.log(A.data.num); //10,A中属性值并没有改变,说明是深拷贝

通过这种方式能实现深层拷贝,而且能自由控制拷贝是如何进行的,如:当B中有和A同名的属性,要不要重新赋值?这些都可以进行控制,但是代码相对复杂一些。

JSON.parse()和JSON.stringify

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var B=JSON.parse(JSON.stringify(A));
B.data.num=5;
console.log(A.data.num); //10,A中属性值并没有改变,说明是深拷贝

用这种方式实现深拷贝的时候要 注意 , 函数是无法进行拷贝的,会被丢失 ,上述代码中B也并没有拷贝出A中的say函数,这和JSON.stringify方法的规则有关系,它在序列化的时候会直接忽略函数,因此最后A中的say函数没有被拷贝到B,关于JSON.stringify序列化的具体规则见JSON.stringify指南。

深拷贝总结

递归:使用递归进行深拷贝时比较灵活,但是代码较为复杂;

JSON对象:JSON对象方法实现深拷贝时比较简单,但是当拷贝对象包含方法时,方法会被丢失;

因此使用者可按自身的使用场景来选择拷贝方式

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-09-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
实现浅拷贝与深拷贝
Js包含基本数据类型与引用数据类型两种不同的数据类型的值,深拷贝与浅拷贝的概念只存在于引用数据类型。对于引用类型,浅拷贝是拷贝了指向这个对象堆内存的指针,是拷贝了对原对象引用,深拷贝是拷贝了该对象的所有属性到一个新的对象,若是原对象的某属性依然引用了其他对象,那么需要将原对象引用的其他对象一并进行深拷贝,并不断递归进行。对于基本数据类型是不存在深拷贝与浅拷贝的概念的,如果将一个基本数据类型变量的值赋值到另一个变量,那么新变量的值是对于原变量值的复制而不是引用,如果必须要按照深浅拷贝的概念理解的话,对于基本数据类型的复制可以理解为按值深拷贝。
WindRunnerMax
2020/08/27
6400
细说浅拷贝与深拷贝
js的浅拷贝与深拷贝在业务中时常有用到,关于浅拷贝与深拷贝的剖析文章层出不穷,本文是笔者对于深拷贝与浅拷贝的理解,一起来夯实js语言基础知识的理解吧。
Maic
2022/07/28
4400
细说浅拷贝与深拷贝
JavaScript中浅拷贝和深拷贝的区别和实现
要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型。JavaScript有两种数据类型,基础数据类型和引用数据类型。
Javanx
2019/09/05
6400
JavaScript中浅拷贝和深拷贝的区别和实现
前端的浅拷贝和深拷贝区别_解构赋值是深拷贝还是浅拷贝
对于浅拷贝来说,比如一个数组(数组是一种对象),只要我们修改了一个拷贝数组,那么原数组也会改变!
全栈程序员站长
2022/11/14
4870
前端的浅拷贝和深拷贝区别_解构赋值是深拷贝还是浅拷贝
深入理解JavaScript中的堆与栈 、浅拷贝与深拷贝
学了这么长时间的JavaScript想必大家对浅拷贝和深拷贝还不太熟悉吧,今天在项目中既然用到了,早晚也要理清一下思路了,在了解之前,我们还是先从JavaScript的数据类型存放的位置 堆栈开始说起吧!
青梅煮码
2023/03/02
2420
JavaScript中浅拷贝和深拷贝的区别和实现
要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型
tianyawhl
2019/04/04
5350
JavaScript中浅拷贝和深拷贝的区别和实现
JavaScript 数据结构与算法之美 - 栈内存与堆内存 、浅拷贝与深拷贝
栈内存与堆内存 、浅拷贝与深拷贝,可以说是前端程序员的内功,要知其然,知其所以然。
夜尽天明
2019/07/10
6630
JavaScript 数据结构与算法之美 - 栈内存与堆内存 、浅拷贝与深拷贝
JavaScript之深拷贝和浅拷贝
工作中会经常遇到操作数组、对象的情况,你肯定会将原数组、对象进行‘备份’ 当真正对其操作时发现备份的也发生改变,此时你一脸懵逼,到时是为啥,不是已经备份了么,怎么备份的数组、对象也会发生变化。 如果你对拷贝原理理解的不透彻,此文或许能提供一点帮助。
Jack Chen
2018/12/13
5190
JavaScript之深拷贝和浅拷贝
【面试题解】JavaScript的深浅拷贝,如何手写深拷贝?
本系列面试题旨在学会相关知识点,从而轻松应对面试题的各种形式,本文讲解了 JavaScript 中拷贝的相关知识,以及如何手写深浅拷贝。
一尾流莺
2022/12/10
4340
【面试题解】JavaScript的深浅拷贝,如何手写深拷贝?
大全!JavaScript中深浅拷贝内部方法与手写函数
怎么理解这句话:浅拷贝过程实质上是创建了一个新的变量,但这个新变量与原变量指向同一个内存地址上的对象。这意味着原对象和拷贝对象共享相同的数据结构和内部状态。因此,对拷贝对象所做的任何修改,如果涉及到修改共享的数据结构,也会影响到原始对象。同样的,原始对象所做的任何修改,如果涉及到修改共享的数据结构,也会影响到拷贝对象。
用户6256742
2024/08/13
1560
javaScript中的浅拷贝 vs 深拷贝
在前端的数据处理当中,有时候往往需要对原有的数据进行克隆拷贝一份,然后在进行操作,但是又不能影响原来的数据
itclanCoder
2020/10/28
6950
javaScript中的浅拷贝 vs 深拷贝
什么是深拷贝;深拷贝和浅拷贝有什么区别;深拷贝和浅拷贝有哪些方法(详解)
在JavaScript中,对象和数组是引用类型,这意味着当你将它们赋值给一个变量或者作为函数参数传递时,你实际上是在传递一个指向内存中对象的引用,而不是对象本身的副本。这就涉及到了深拷贝和浅拷贝的概念。
watermelo37
2025/01/22
1770
什么是深拷贝;深拷贝和浅拷贝有什么区别;深拷贝和浅拷贝有哪些方法(详解)
对象的浅拷贝和深拷贝
原文链接:https://note.noxussj.top/?source=cloudtencent 以下主要介绍了正常情况下的拷贝、浅拷贝、深拷贝三种方式的区别。 正常拷贝:复制一个对象,它们的内存
菜园前端
2023/05/21
2510
面试官:你知道哪些深浅拷贝方式吗?
这个方法是可以实现拷贝的,但是我们需要注意的是,当属性对应的一个值是引用类型时,我们会发现这也是一个浅拷贝:
程序员法医
2022/08/11
1990
一篇文章彻底搞懂浅拷贝和深拷贝的区别_深拷贝和浅拷贝的题
由博主《前端初级工程师面试系列一JS基础》文章一JS变量类型引伸的考点,变量类型分为基本类型和引用类型,那么在变量拷贝赋值时,也是不一样的,分为浅拷贝和深拷贝,是面试中常考的知识点,也是实际开发中经常会用到的内容。
全栈程序员站长
2022/11/10
4910
一篇文章彻底搞懂浅拷贝和深拷贝的区别_深拷贝和浅拷贝的题
深浅拷贝
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
hss
2022/02/25
3010
一文搞懂JS中的赋值·浅拷贝·深拷贝
为什么写拷贝这篇文章?同事有一天提到了拷贝,他说赋值就是一种浅拷贝方式,另一个同事说赋值和浅拷贝并不相同。我也有些疑惑,于是我去MDN搜一下拷贝相关内容,发现并没有关于拷贝的实质概念,没有办法只能通过实践了,同时去看一些前辈们的文章总结了这篇关于拷贝的内容,本文也属于公众号【程序员成长指北】学习路线中【JS必知必会】内容。
coder_koala
2019/07/30
3.2K0
一文搞懂JS中的赋值·浅拷贝·深拷贝
关于深拷贝与浅拷贝问题的个人理解
这是我大一上学期遇到的一个“怪现象”,之所以说是“怪现象”,是因为当时不懂这里面的原因,只因为它没有按照我的预想结果那样。
JoviCheng
2019/09/05
6570
赋值、浅拷贝、深拷贝的区别
基本类型数据保存在在栈内存中 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中。
木子星兮
2020/07/16
1.1K0
深拷贝浅拷贝和赋值的差异
在工作中我们经常会用到深拷贝与浅拷贝,但是你有没有去分析什么场景下使用它,为什么需要使用呢,深浅拷贝有何异同呢,什么是深拷贝呢,如何实现呢,你会有这些问题吗,今天就为大家总结一下吧。
Snine
2022/02/11
4670
推荐阅读
相关推荐
实现浅拷贝与深拷贝
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文