当前位置: 首页 > news >正文

前端深拷贝与浅拷贝的实现

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)的用法。 一、为什么要做曲面细分 之前通过法…...

【位运算】消失的两个数字(hard)

消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found"​, "n…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

P10909 [蓝桥杯 2024 国 B] 立定跳远

# P10909 [蓝桥杯 2024 国 B] 立定跳远 ## 题目描述 在运动会上&#xff0c;小明从数轴的原点开始向正方向立定跳远。项目设置了 $n$ 个检查点 $a_1, a_2, \cdots , a_n$ 且 $a_i \ge a_{i−1} > 0$。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时&#xff0…...

新版NANO下载烧录过程

一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...