记录-实现深拷贝的四种方式

news2024/12/23 13:35:10

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

概念介绍

深拷贝:在堆内存中重新开辟一个存储空间,完全克隆一个一模一样的对象 浅拷贝:不在堆内存中重新开辟空间,只复制栈内存中的引用地址。本质上两个对象(数组)依然指向同一块存储空间

第一种:递归方式(推荐,项目中最安全最常用)

使用递归的方式进行对象(数组)的深拷贝

奉上已封装的深拷贝函数👇

	//函数拷贝
    const copyObj = (obj = {}) => {
    		//变量先置空
            let newobj = null;  

            //判断是否需要继续进行递归
            if (typeof (obj) == 'object' && obj !== null) {
                newobj = obj instanceof Array ? [] : {};
                //进行下一层递归克隆
                for (var i in obj) {
                    newobj[i] = copyObj(obj[i])
                }
                //如果不是对象直接赋值
            } else newobj = obj;
            
            return newobj;    
        }

上方函数的使用方式👇

//模拟对象
let obj = {
	numberParams:1,
	functionParams:() => {
		console.log('昨天基金全是绿的,只有我的眼睛是红的');
	},
	objParams:{
		a:1,
		b:2
	}
}

const newObj = copyObj(obj); //这样就完成了一个对象的递归拷贝

obj.numberParams = 100;  //更改第一个对象的指
console.log(newObj.numberParams); //输出依然是1 不会跟随obj去改变

第二种:JSON.stringify() ;(这个不推荐使用,有坑)

这个方法有坑,详细讲解请看我另一篇文章 “使用JSON.stringify进行深拷贝的坑” 以下是代码示例

let obj = {
	a:1,
	b:"基金亏太多,终有一天,你站上了天台,我卧上了轨道。来生我们有说有笑。"
}

//先转为json格式字符,再转回来
let newObj = JSON.parse(JSON.stringify(obj));

obj.a = 50;
console.log(newObj.a); //输出 1  

普通的对象也可以进行深拷贝,但是!!! 当对象内容项为number,string.boolean的时候,是没有什么问题的。但是,如果对象内容项为undefined,null,Date,RegExp,function,error的时候。使用JSON.stringify()进行拷贝就会出问题了。 详细讲解请查看我的另一篇文章“使用JSON.stringify()进行深拷贝的坑”

第三种:使用第三方库lodash中的cloneDeep()方法

是否推荐使用,看情况吧。如果我们的项目中只需要一个深拷贝的功能,这种情况下为了一个功能引入整个第三方库就显得很不值得了。不如写一个递归函数对于项目来说性能更好。

lodash.cloneDeep()代码示例👇

import lodash from 'lodash';

let obj = {
	a: {
	    c: 2,
	    d: [1, 3, 5],
	    e:'阿巴阿巴'
	  },
	  b: 4
}

const newObj = lodash.cloneDeep(obj);

obj.b = 20;
console.log(newObj.b); //输出 4; 不会改变

实际上,cloneDeep()方法底层使用的本来就是递归方法。只是在外层又封装了一层而已。

所以,如果不是原先项目中有使用 lodash 这个库的话,大可不必为了这一个功能而去引入它。

文章上方有提供进行深拷贝的函数,推荐使用。大家可自取。

第四种:JQuery的extend()方法进行深拷贝(推荐在JQ中使用)

这个方法仅适用于JQuery构建的项目。 JQuery自身携带的extend()方法可以进行深拷贝,不用自己写递归也不用引入第三方库还没什么坑。

在JQuery项目中的使用方式👇

let obj = {
	a: {
	    c: 2,
	    d: [1, 3, 5],
	    e:'阿巴阿巴'
	  },
	  b: 4
}

let newObj= $.extend(true, {}, obj1);  //拷贝完成

obj.b = 20;

console.log(newObj.b); //输出 4 

总结

进行深拷贝的方法

  • 递归函数 (推荐使用,项目中使用的更多,更小,更安全)
  • JSON.stringify() 和JSON.parse() ; (不推荐使用,如果遇到Function,Date等类型的变量容易出现一些意料之外的问题)
  • 第三方库lodash的cloneDeep()方法 (就情况而定,如果项目中原先就有lodash这个第三方库,可以使用,否则还是推荐使用递归函数。不然成本太高。)
  • JQuery的extend()函数 (推荐在JQuery项目中使用,其他项目依然推荐是用递归函数)

本文转载于:

https://juejin.cn/post/7109843641677398053

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

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

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

相关文章

Python双向循环链表的操作

目录 一、双向循环链表 双向循环链表图 二、双向循环链表的操作 1、判断链表是否为空 2,链表长度 3,遍历整个链表 4,在链表头部添加元素 5、链表尾部添加元素 6,在指定位置插入元素 7,修改指定位置的元素 8&a…

被裁后找不到工作,本质上是因为原来的能力就配不上高薪,如果技术好,根本不怕被裁,相当于白送n+1!...

被裁员后,能要求公司补缴公积金吗? 一位网友问: 被裁员了,要求公司把历史公积金全部足额缴纳,现在月薪2.3万,但公司每个月只给自己缴纳300元公积金,结果一次补了二十多万,一次性取出…

进程等待、进程替换

目录 进程等待 waitpid函数 wait函数 进程替换 进程等待 进程等待的意义 如果子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。 另外,进程一旦变成僵尸状态,那就刀枪不入&#xff…

5.5G的关键一跳!将数智未来照进现实

编辑:阿冒 设计:沐由 作为数字时代的三大思想家之一,乔治吉尔德在1993年就指出,未来25年内主干网的带宽每6个月增长一倍,其增长速度是摩尔定律预测的CPU增长速度的3倍。 这就是著名的吉尔德定律(Gilder’s …

Qt开源项目:校医院远程诊断系统介绍

本人研一参考技术书籍开发的一款Qt程序,两年前已上传到GitHub,有兴趣的同学可以去看看。可能之前上传的项目不够完整,导致有一些同学没有在自己的环境上跑通,所以今天将整个工程都重新上传一遍,包括使用到的opencv的动…

Lambda 表达式中的变量必须是 final 的吗

如果我们定义了一个变量,想要在Lambda 表达式中修改变量的值,编译器会发出警告:“variable used in lambda expression should be final or effectively final”。 比如对一个list进行遍历,遍历的过程中对i进行操作 Java 规范中…

浅理解 ES6 新增的数组方法Array.of() 和 Array.from()

文章目录 📋前言🎯Array.of() 方法🎯Array.from() 方法🎯二者区别📝最后 📋前言 在前端开发的面试过程中, ES6 新增是一个很常见的考点,比如说箭头函数、模板字符串、let 和 const …

宁波汽车运输集团:引入二维码技术,实现车辆精细化管理

宁波市汽车运输集团有限公司是宁波市道路货运业的龙头企业之一,主营全国各地的普通货运以及货物专用运输(集装箱、罐式)。 作为汽车运输集团,车辆的安全问题极其重要。因此,公司设备安全部门要求每个驾驶员在作业之前…

netfilter filter表(二)

这次继续分析filter表,不同与之前的分析方式,这次通过将内核中的数据打印出来,对比结构关系图来分析。这是本次分析涉及的几个数据结构: struct xt_table { struct list_head list; /* What hooks you will enter on */ unsigned …

4、SpringBoot接收和响应xml报文请求

背景 平时开发的接口,基本是使用 json 格式的请求报文。然而,有时候也避免不了有 xml 报文请求的场景,最近就遇到了这种情况,在此记录下。另外,工程中使用的是 controller-service……这种结构。 xml请求报文&#x…

链表(JS实现)

📝个人主页:爱吃炫迈 💌系列专栏:数据结构与算法 🧑‍💻座右铭:道阻且长,行则将至💗 文章目录 链表链表的分类创建链表LinkedList类的骨架 实现链表的方法push尾部添加元…

chatgpt智能提效职场办公-ppt怎么蒙层

作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 在 PowerPoint 中添加蒙版图层,可以在幻灯片中创建一个半透明的矩形或形状,并在其上方添加或放置其他对象。 下…

FPGA终于可以愉快地写代码了!Vivado和Visual Studio Code黄金搭档

如果你是一位FPGA开发者,那么你一定会对VIvado这款软件非常熟悉。但是,对于vivado兼容的第三方编辑器软件,你知道Visual Studio Code吗?这是个非常不错的选择,Visual Studio Code搭配众多插件,能让你FPGA开…

【SpringBoot】一:SpringBoot的基础(下)

文章目录 1.外部化的配置1.1 配置文件基础1.1.1 配置文件格式1.1.2 application文件1.1.3 application.properties1.1.4 application.yml1.1.5 environment1.1.6 组织多文件1.1.7多环境配置 1.2 绑定Bean1.2.1 简单的属性绑定1.2.2 嵌套Bean1.2.3 扫描注解1.2.4 处理第三方库对…

【移动端网页布局】移动端网页布局基础概念 ② ( 视口 | 布局视口 | 视觉视口 | 理想视口 )

文章目录 一、视口1、布局视口 ( 网页大小 | 网页大小 > 设备大小 )2、视觉视口 ( 设备大小 | 网页大小 > 设备大小 )3、理想视口 ( 网页大小 设备大小 ) 一、视口 浏览器 显示 网页页面内容 的 屏幕区域 被称为 " 视口 " ; 视口分为以下几个大类 : 布局视口…

项目协同中的git

在远程代码仓库(云效,gitee,github,Coding等)新建一个代码库, 我使用的云效 新建一个develop分支,后续所有人的提交代码都合并到develop分支上面,一般develop分支是用来开发用的&…

尚融宝22-提交借款申请

目录 一、需求介绍 二、图片上传 (一)前端页面 (二)实现图片上传 三、数据字典展示 (一)后端 (二)前端 四、表单信息提交 (一)后端 1、VO对象&…

嵌入式工程师如何快速的阅读datasheet的方法

目录 ▎从项目角度来看datasheet ▎各取所需 ▎最后 Datasheet(数据手册)的快速阅读能力,是每个工程师都应该具备的基本素养。 无论是项目开始阶段的选型还是后续的软硬件设计,到后期的项目调试,经常有工程师对着英…

06-Node.js—模块化

目录 1、介绍1.1 什么是模块化与模块 ?1.2 什么是模块化项目 ?1.3 模块化好处 2、模块暴露数据2.1 模块初体验2.2 暴露数据2.2.1 module.exports value2.2.2 exports.name value 3、导入(引入)模块4、导入模块的基本流程5、CommonJS 规范参考 1、介绍…

使用RabbitMQ的手动接收模式:消息第二次入队Failed to declare queue

问题&#xff1a;在rabbitMQ测试使用手动接收模式时发生 Failed to declare queue错误 : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code406, reply-textPRECONDITION_FAILED - unknown delivery tag 1, class-id60, method-id80…