面试题:深拷贝和浅拷贝(+内存图)

news2024/11/17 6:52:40

深拷贝和浅拷贝主要是针对对象的属性是对象(引用类型)

一、基本类型和引用类型的区别 

         1)、基本类型:就是值类型,即在变量所对应的内存区域存储的是值。

         2)、引用类型:就是地址类型。    

                何为地址:地址就是编号,要地址何用,就是为了容易找到。每个人的家里为什么要有一个唯一的地址,就是在邮寄时,能够找到你家。 比如:我们最早的超市存包的格子,每个格子都有个编号,你存包时,服务员会把你的东西放在某个格子里,再把这个格子的编号给你(一个牌子)。你购物完毕取包时,直接给服务员你的牌子(有编号),服务员根据你的编号就会找到你的包。这个编号就是格子的地址。内存也是一样的,每个内存都有一个编号,方便cpu查找。要不然,浩瀚的内存海洋,cpu要找到数据靠啥找。 以上的变量arr就是引用类型,arr所对应的内存中存储着地址,真正的数据是在地址对应的内存区域里,就像,你填写简历时,会在简历的那张纸上写上你家的地址。简历上写你家地址的地方就相当于arr。而你家是根据这个地址可以找到的。简历上写你家地址的地方就相当于引用着你家(可以想象一根无形的线牵引着你家,在简历上的这根无形的线,顺藤摸瓜就能找到你家)。所以叫做引用类型。

 二、基本类型和引用类型在赋值时内存的变化

        其实我们可以认为,赋值就是在拷贝 。

  •         基本类型:

        

  •         引用类型 :

        如果给arr[0]赋值的话,arr1[0]的值也会发生变化,因为,arr和arr1保存着相同的地址,它门两个引用的数据是共享的。

        如果在上面的基础上增加一句代码:arr[0]=10;那么内存将会有如下变化:

三:基本类型和引用类型作为函数参数的区别

        1、基本类型作为函数的参数 

 

        2、引用类型作为函数的参数: 

 

四:深拷贝和浅拷贝实现: 

所谓拷贝,就是赋值。把一个变量赋给另外一个变量,就是把变量的内容进行拷贝。把一个对象的值赋给另外一个对象,就是把一个对象拷贝一份。

1、基本类型

因为,基本类型赋值时,赋的是数据(所以,不存在深拷贝和浅拷贝的问题)。

   如: 

   Var x = 100;

   Var y = x; //此时x和y都是100;

   如果要改变y的值,x的值不会改变。

2、引用类型有问题

        因为,引用类型赋值时,赋的值地址(就是引用类型变量在内存中保存的内容),强烈建议把前面的第二点(基本类型和引用类型在赋值时内存的变化)多看几遍,以保证理解深刻。这样,一劳永逸,以后在碰到任何跟引用类型有关的话题(如:继承时,父类的属性是引用类型)都没有问题。

      如:

var arr1 = new Array(12,23,34)

Var arr2 = arr1;//这就是一个最简单的浅拷贝

        如果要改变arr2所引用的数据:arr2[0]=100时,那么arr1[0]的值也是100。

        原因就是 arr1和arr2引用了同一块内存区域(以上的第二点中有体现)。

        这是最简单的浅拷贝,因为,只是把arr1的地址拷贝的一份给了arr2,并没有把arr1的数据拷贝一份。所以,拷贝的深度不够。

3、用json对象的方式(也是引用类型)来演示浅拷贝和深拷贝 

        1)、定义一个json对象(对象的属性也是对象) 

var p = {
	"id":"007",
	"name":"刘德华",
	"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
}

内存图:

 


  2)、把该对象p进行复制一份

               (一)浅拷贝

var p2 = {};
for(let key in p){
	p2[key] = p[key];	
}
p2.books[0] ="四国";
console.log(p2);
console.log(p);

        在控制台中打印的结果(p和p2的books[0]都变成了“四国”): 

 

        内存: 

        


                (二)深拷贝(初步)

var p2 = {};
for(let key in p){
	if(typeof p[key]=='object'){
		p2[key]=[];//因为,我上面写的是数组,所以,暂时赋值一个空数组.
		for(let i in p[key]){
			p2[key][i] = p[key][i]
		}
	}else{
		p2[key] = p[key];
	}
}
p2.books[0] ="四国";
console.log(p2);
console.log(p);

        在控制台中打印的结果(只有p2的books[0]变成了“四国”) 

 

        内存:                


  (三)深拷贝(最终) 

         3.1、深拷贝_如果属性都是json对象,那么用递归的方式

//如果对象的属性是对象(引用类型),属性的属性也是引用类型,即层层嵌套很多.怎么办,只能递归

//如下对象,要复制:

var p = {
	"id":"007",
	"name":"刘德华",
	"wife":{
		"id":"008",
		"name":"刘德的妻子",
		"address":{
			"city":"北京",
			"area":"海淀区"
		}
	}
}
 
//写函数
function copyObj(obj){
	let newObj={};
	for(let key in obj){
		if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
			newObj[key] = copyObj(obj[key])
		}else{//基本类型,直接赋值
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
 
let pNew = copyObj(p);
pNew.wife.name="张三疯";
pNew.wife.address.city = "香港";
console.log(pNew);
console.log(p);

 

 

         3.2、深拷贝_如果属性是数组等非键值对的对象

        就得单独处理:要么给数组增加一个自我复制的函数(建议这样做),要么单独判断。 

//给数组对象增加一个方法,用来复制自己
Array.prototype.copyself = function(){
	let arr = new Array();
	for(let i in this){
		arr[i]  = this[i]
	}
	return arr;
}
 
var p = {
	"id":"007",
	"name":"刘德华",
	"books":new Array("三国演义","红楼梦","水浒传")//这是引用类型
}
 
function copyObj(obj){
	let newObj={};
	for(let key in obj){
		if(typeof obj[key] =='object'){//如:key是wife,引用类型,那就递归
			newObj[key] = obj[key].copyself();
		}else{//基本类型,直接赋值
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
 
var pNew = copyObj(p);
pNew.books[0] = "四国";
console.log(pNew);
console.log(p);  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/682437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kubeadm 部署k8s实现并且演示滚动不停服务更新

1. 环境准备 在开始之前,部署Kubernetes集群机器需要满足以下几个条件: 一台或多台机器,操作系统 CentOS7.x-86_x64;硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多;集群中…

【Activiti】原理

一、核心类 RepositoryService:部署管理流程资源,如bpmn文件、附件等等;RuntimeService:操作运行时的流程;TaskService:流程中任务的信息;HistoryService:流程的历史信息&#xff1…

ZYNQ——按键和LED关联实验

ZYNQ 7020黑金开发板的PL端有四个LED,如下图所示。 PL端也有四个KEY,如下图所示。 本文将把这四个按键和四个LED一一对应起来,在按键按下或松开时,对应的LED产生亮或灭的信号。 在原理图中找到PL端的LED和KEY如下图所示。 通过…

成为python爬虫工程师需要哪些知识?

爬虫(Web crawler)是一种自动化程序,用于从互联网上抓取、解析和提取网页数据。它模拟浏览器行为,通过发送HTTP请求获取网页内容,并通过解析网页源代码或DOM结构,提取所需的信息。以python爬虫为例&#xf…

优思学院|作业标准和标准化作业有何区别?傻傻搞不清?

作业标准和标准作业是两个在生产和制造环境中具有重要意义的概念。尽管它们看似相似,但实际上它们在定义、目的和实施方法上存在显著差异。本文将探讨作业标准和标准作业的区别,以及它们在工作场所中的作用和重要性。 1. 引言 在制造领域中&#xff0c…

JDBC小记——SQL注入及预编译操作对象、批处理

目录 SQL注入 预编译操作对象 自定义JDBC工具类 1.创建配置文件 2.配置 3.在工具类中使用配置文件 批处理 注意事项 SQL注入 SQL注入是黑客对数据库进行攻击的常用手段之一,他们拼接一些恶意的sql语句,来获取他们想要的数据。 例: s…

Bpmn.js流程建模结合业务整合工作流(一)

bmpn.js是什么? 先上图 初步认识bpmn.js 相关文档直接上链接 全网最详bpmn.js教材-基础篇 - 掘金bpmn.js是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成. 因为公司业务的需要因而要在项目中使用到bpmn.js,但是由于bpmn.js的开发者是国外友人, 因此国…

【2023年中总结】是的,我从一家世界前百强企业毕业了,进入了一家只有20人的小企业。。。

我的2023-上 🕐 一、引言🕜 二、新年🕙 三、措手不及🕥 四、抉择🕚 五、适应🎉测试驱动开发🎉角色的转变🎉工作环境和生活环境的转变🎉工作态度 🕦 六、挑战&…

【裸机开发】定时器中断(EPIT)

EPIT 是周期性中断定时器,会定期调用指定的中断服务函数,其实可以看做是一种IRQ的外设中断,对应的中断ID是88(5632)或者 89(5732)。 目录 一、定时器计数流程 二、寄存器解析 1、EPIT1_CR 2…

骨传导耳机、运动耳机推荐:南卡OE开放式TWS耳机值得买吗?南卡OE测评

目前,如果说到骨传导耳机、蓝牙耳机想必大家都很熟悉,那你了解TWS耳机么? 如果说iPhone“重新定义”了智能手机,那么AirPods就重新定义了耳机——它“断”了耳机与手机/播放器间的连线,还将左右耳彼此间的连线彻底摒弃…

SimpleDateFormat显示24小时和12小时时间格式

public static void main(String[] args) throws Exception {MainTest1 mainTest1 new MainTest1();mainTest1.dateFormat();} yyyy-MM-dd HH:mm:ss格式显示的时间为:2017-06-12 18:01:06 yyyy-MM-dd hh:mm:ss格式显示的时间为:2017-06-12 06:01:06

二章:VMvare虚拟机的安装+VMvare安装winServer2008

目录 一、Vmware软件安装 二、Vmware软件注册 三、Vmware配置虚拟机-1 四、Vmware配置虚拟机-2 五、Vmware配置虚拟机-3 六、Vmware安装windows server 2008 一、Vmware软件安装 第一步 双击安装程序,点击下一步。 第二、三步 勾选接受许可,点击下一步。…

SAM【1】:Segment Anything

文章目录 前言1. Abstraction & Introduction1.1. Abstraction1.2. Introduction 2. Segment Anything Model2.1. Segment Anything Task2.1.1. Task2.1.2. Pre-training2.1.3. Zero-shot transfer 2.2. Segment Anything Model Methods2.2.1. Image Encoder2.2.2. Prompt …

python:并发编程(二十三)

前言 本文将和大家一起探讨python并发编程的实际项目:win图形界面应用(篇五,共八篇),系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。 本文为python并…

微信小程序快速入门【二】

微信小程序快速入门【二】 文章目录 微信小程序快速入门【二】👨‍🏫内容1:背景👨‍⚖️内容2:项目结构👨‍💻内容3:项目配置文件app.json👨‍🚀内容4&#x…

SpringBoot使用入门和案例实现

目录 1. 在pom.xml中添加依赖2. 编辑resources/application.properties3. 编写springboot的主程序4. 编写Controller程序5. IDEA本地测试6. 打包上传到服务器运行 1. 在pom.xml中添加依赖 步骤如下: 添加springboot的parent依赖添加springboot的starter-web依赖。…

osip开源库在windows平台上编译

背景 之前写过一篇关于sip协议栈选型的文章,最终采用了osip 2.3.6版本,文章中说明了为什么采用osip协议栈,以及为什么采用2.3.6版本。现在Linux上的产品已经基本满足需求了,接下来我们打算开发一套客户端和服务端对接&#xff0c…

电子邮件机器人和聊天机器人如何使您的客户支持受益?

当我们谈论客户支持中的人工智能时,通常会想到基于Web的聊天机器人。然而,现代人工智能的进步使电子邮件机器人成为客户支持自动化的下一个风口,使组织能够满足人们对于快速便捷的全渠道体验的期望。 有些人认为,与Facebook Mess…

“兆易创新杯”第十八届中国研究生电子设计竞赛有感

今年的电赛给我的感觉是时间真的紧张,可能是因为去年有疫情原因影响所以能准备的时间到七月份,今年不到月底就要全部出成品。我们团队一直在自研一款增强现实眼镜,从硬件设计到软件实现全部由我和另外两个小伙伴一起完成,所以就把…

matlab实现声音录制与左右声道分离

基础知识 1.MATLAB识别的常用语音信号类型: WAV格式 TXT格式 2.读取wav格式语音用函数:wavread 常用格式: ywavread(‘语音文件名’) [y,fs]wavread (‘语音文件名’) 用于读取语音,采样值放在向量y中,fs表示采样频率。 3.读取wav格式语音用…