前端深拷贝与浅拷贝的实现
1、浅拷贝和深拷贝的定义
1.1、浅拷贝
有两种方式,一种是把一个对象里面的所有的属性值和方法都复制给另一个对象,另一种是直接把一个对象赋给另一个对象,使得两个都指向同一个对象。浅拷贝对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。
1.2、深拷贝
深拷贝是指拷贝对象的具体内容,其内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象互相不影响,互不干涉。
数据类型的值传递和地址传递
JavaScript的数据类型可以分为基本数据类型和引用数据类型
基本数据类型有:Number、String、Boolean、Null、Undefined、Symbol
引用数据类型有:Object、Function、Array、Regexp、Date
普通数据类型和对象的存储方式:
普通数据类型一般是存储在栈中的,而对象一般是存储在堆中的,同时在栈中存放了一个地址数据指向堆中的数据。当调用对象时,首先会获取栈中的地址,根据该地址去堆中找到该对象数据。
针对普通类型,在赋值过程中一般是值传递
//Number
var num1=12;
var num2=num1;
num2=34;
console.log(num1,num2);//12,34
//String
var str1="abc";
var str2=str1;
str2="def";
console.log(str1,str2);//abc,def
针对引用类型中的对象和数组,在赋值过程中一般是地址传递
//对象
var obj1 = { name: 'jack' };
var obj2 = obj1; //复制obj1的引用
obj2.name = 'mary';
//此时obj1和obj2全都指向一个地址,修改地址值,obj1和obj2的值都会改变
console.log(obj1.name, obj2.name);//mary,mary
// []
a = ['a', 'b', 'c']; b = a; b[1] = 'd';
console.log(a, b)
2、浅拷贝实现的具体方式
2.1、数字方法slice()
var arr1 = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var arr2 = arr1.slice();//复制arr1在栈中的引用地址
arr2[0].number = 9//将复制过来的引用地址的指向修改为9,所以arr和arr2都会改变
console.log(arr1[0].number, arr2[0].number);//9,9原因:
arr2拷贝了arr1在栈内存中的地址,也就是arr2和arr1共用存储在堆内存的数据;同理得,当arr2发生改变的时候,arr1也会随之改变。
2.2、Object.assign
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。
var arr1 = [//两层数据
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var obj1 = { name: 'jack' }//一层数据
var obj2 = Object.assign({}, obj1);//此时obj1为一层数据,复制的是对象中的属性值
obj2.name = 'mary'
var arr2= Object.assign({}, arr1)//复制的是数组中的对象在栈中的的引用地址
arr2[0].number = 99
console.log(obj1.name, obj2.name, arr1[0].number, arr2[0].number);//jack mary 99 99
2.3、for…in…
通过for…in…遍历对象将源对象的值拷贝到另一个对象上,并返回另一个对象。浅拷贝只能遍历一层对象,当数据是嵌套对象则需要深拷贝。
var qianCopy = function (obj) {
var result= obj.constructor();//声明参数的一个空构造函数
// 遍历对象中的属性及方法
for (var key in obj) {
// 判断对象有没有相应的key
if (obj.hasOwnProperty(key)) {
// 把对象相应key对象的值赋值给另外一个对象相应的key对应的值
result[key] = obj[key];
}
}
return result
}
var obj1 = { name: 'jack' };
var obj2 = qianCopy(obj1); //复制obj1的引用
obj2.name = 'mary';
//此时obj1和obj2全都指向一个地址,修改地址值,obj1和obj2的值都会改变
console.log(obj1.name, obj2.name);//jack,mary
3、深拷贝的具体实现
3.1、JSON.parse(JSON.stringify())
JSON.parse(JSON.stringify())一般用于深拷贝:JSON.stringify()将JS对象序列化转化为JSON字符串,再利用JSON.parse()反序列化,将JSON字符串还原成对象。该方法只能用于可枚举属性。
var arr1 = [
{ number: 1 },
{ number: 2 },
{ number: 3 }
];
var arr2 = JSON.parse(JSON.stringfy(arr1))//此时是将arr1中所有属性的值复制给arr2,两者相互独立
arr2[0].number = 199
console.log(arr1[0].number, arr2[0].number);//1,199
当然JSON.parse(JSON.stringify())并不是一种完美实现深拷贝的方法,存在以下缺陷:
1.当深拷贝对象为函数、Undefined时,会把函数、Undefined丢失,无法拷贝。
2.当深拷贝对象为Regexp、Error对象,序列化结果为空对象
3.当深拷贝对象中存在NaN、infinity、-infinity时,序列化会变成Null
3.2、递归
面试题:使用递归完成深拷贝对象
function shenCopy(obj){
//创建参数的构造函数对象
var result=obj.constructor();
if(typeof obj!==Object){//当传入参数不为Object类型时,直接返回该参数
return obj;
}else{
for(let key in obj){
//递归核心:将嵌套对象递归得到的返回值赋予新建的构造对象
result[key]=shenCopy(obj[key]);
}
}
return result;
}
相关文章:
前端深拷贝与浅拷贝的实现
1、浅拷贝和深拷贝的定义 1.1、浅拷贝 有两种方式,一种是把一个对象里面的所有的属性值和方法都复制给另一个对象,另一种是直接把一个对象赋给另一个对象,使得两个都指向同一个对象。浅拷贝对内存地址的复制,让目标对象指针和源…...

哆啦百宝箱APP
专门为年轻人设计的APP,主打的免费、无恶心广告、不获取任何个人信息。 哆啦百宝箱 ● 永久免费 ● 无恶心广告 ● 种类巨多 ● 全民参与 ● 爆款功能 ● 用心创造 哆啦百宝箱 提供了从日常、图片、查询、设备、趣味、娱乐等多方面的功能, 操作简单&a…...

lv9 嵌入式开发 数据库sqlite
1 数据库基本概念 数据(Data) 能够输入计算机并能被计算机程序识别和处理的信息集合 数据库 (Database) 数据库是在数据库管理系统管理和控制之下,存放在存储介质上的数据集合 2 常用的数据库 大型数据库…...

「Verilog学习笔记」异步复位的串联T触发器
专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 这道题目里我们有两个需要明确的点: 1. 什么是异步复位 2. 什么是串联的T触发器 关于第一个点,可以看我的这篇文章,已经整理好了&a…...

什么是51单片机,,如何写代码,并且烧录?
文章目录 1.单片机介绍2.Keil 5操作1.打开Keil 5 3 新建工程3.添加文件并写代码4.添加到group5,设置6.check7.编译8.打开头文件9 调整编辑器 4.烧录1.烧录程序2.串口查询 5.Debug1.首先编译2.调试3.查询 6 51单片机汇编指令1.格式2.符号3.寻址4.数据传送与交换指令5.交换指令6 …...
Multer 实现文件上传功能
Multer 实现文件上传功能 前言:Multer 安装和使用1、安装2、使用2-1 前端代码2-2 后端代码3、实现效果前言: post请求一般有4种数据类型: application/x-www-form-urlencodedmultipart/form-dataapplication/jsontext/xml相应后端Express会使用不同的中间件来解析不同类型的…...

Excel·VBA工作表导出为图片
《Excel转图片别再截图啦!用这4个方法,高清且无损!》,excel转为图片一般方法较为简单,那么能否使用vba将excel转为图片 选中区域导出为图片 zoom设置为2,导出图片较为清晰 Sub 选中区域导出为图片()Dim …...

【零基础抓包】Fiddler超详细教学(一)
Fiddler 1、什么是 Fiddler? Fiddler 是一个 HTTP 协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的 HTTP 通讯。Fiddler 提供了电脑端、移动端的抓包、包括 http 协议和 https 协议都可以捕获到报文并进行分析;可以设置断点调试、截取…...

快速入手maven
文章目录 Maven介绍Maven安装和配置基于IDEA的Maven工程创建梳理Maven工程GAVP属性Idea构建Maven JavaSE工程Idea构建Maven JavaEE工程1. 手动创建2. 插件方式创建 Maven工程项目结构说明Maven核心功能依赖和构建管理依赖传递和冲突依赖导入失败场景和解决方案扩展构建管理和插…...
Mysql Binlog日志
Mysql Binlog是二进制格式的日志文件,但是不能把binlog文件等同于OS系统某目录下的具体文件,这是狭隘的。Binlog是用来记录Mysql内部对数据库的改动(只记录对数据的修改操作),主要用于数据库的主从复制、数据同步以及增…...
高级深入--day45
官方站点:GitHub - rmax/scrapy-redis: Redis-based components for Scrapy. scrapy-redis的官方文档写的比较简洁,没有提及其运行原理,所以如果想全面的理解分布式爬虫的运行原理,还是得看scrapy-redis的源代码才行。 scrapy-r…...
shell_66.Linux修改或移除信号捕获
修改或移除信号捕获 要想在脚本中的不同位置进行不同的信号捕获处理,只需重新使用带有新选项的 trap 命令即可: $ cat trapmod.sh #!/bin/bash #Modifying a set trap # trap "echo Sorry...Ctrl-C is trapped." SIGINT # count1 whi…...

5 ip的分配
如上一节所述,需要和其他设备通信,那么需要先配置ip. 1、如何配置ip 1.可以使用 ifconfig,也可以使用 ip addr 2.设置好了以后,用这两个命令,将网卡 up 一下,就可以了 //---------------------------- 使…...
【Python机器学习】零基础掌握StackingClassifier集成学习
如何精确地预测花的种类?一个简单但强大的方法引入了! 在现实生活中,生物学家和园艺爱好者经常面临一个问题:如何准确地识别和分类不同种类的花?这不仅仅是一个纯粹的学术问题,也有实际应用,比如在植物育种、生态研究等方面。为 了解决这个问题,一种叫做堆叠分类(St…...

Spring Boot 常见面试题
目录 1.Spring Boot 快速入门什么是 Spring Boot?有什么优点?Spring Boot 与 Spring MVC 有什么区别?Spring 与 Spring Boot 有什么关系?✨什么是 Spring Boot Starters?Spring Boot 支持哪些内嵌 Servlet 容器?如何设…...

利用大语言模型(LLM )提高工作效率
日常工作就是面向 google/ 百度编程,除了给变量命名是手动输入,大多时候就是通过搜索引擎拷贝别人的代码,或者找到旧项目一段代码拷贝过来使用。这无疑是开发人员的真实写照;然而,通过搜索引擎搜索答案,无疑…...

[Linux打怪升级之路]-信号的产生
前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、信号基础…...
Python教程---Python基础语法
1.程序中的几个基本概念 (1).表达式 表达式就是一个类似于数学公式的东西 比如:10 + 5 8 - 4 表达式一般仅仅用了计算一些结果,不会对程序产生实质性的影响 如果在交互模式中输入一个表达式,解释器会自动将表达式的结果输出 (2).语句 在程序中语句一般需要完成某种功能,…...

echarts 画散点图, x周,y周在指定位置标志一下
文章目录 echarts 画散点图, x周,y周在指定位置标志一下示例一例子二示例三 echarts 画散点图, x周,y周在指定位置标志一下 示例一 let scatterData {data: [[[-0.2, -0.6],[0.4, 0.3],[0.1, 0.4],[0.3, 0.5],[0.09, 0.1],[0.7,…...

Unity地面交互效果——3、曲面细分基础知识
大家好,我是阿赵。 之前介绍了使用动态法线贴图混合的方式模拟轨迹的凹凸感,这次来讲一下更真实的凹凸感制作。不过在说这个内容之前,这一篇先要介绍一下曲面细分着色器(Tessellation Shader)的用法。 一、为什么要做曲面细分 之前通过法…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

对象回调初步研究
_OBJECT_TYPE结构分析 在介绍什么是对象回调前,首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例,用_OBJECT_TYPE这个结构来解析它,0x80处就是今天要介绍的回调链表,但是先不着急,先把目光…...