深拷贝浅拷贝解析,从原理理解深拷贝

这块应该都有过比较深刻的了解了。今天加深下印象和查漏补缺下。

浅拷贝:

let original = { a: 1, b: { c: 2 } };//这边定一个obj,来供拷贝

let shallowCopy = Object.assign({}, original);// let shallowCopy = { ...original };

创建一个浅拷贝对象拷贝原来的对象

shallowCopy.b.c = 3;

修改对象中的深处项

console.log(original); // 输出:{ a: 1, b: { c: 3 } }

console.log(shallowCopy); // 输出:{ a: 1, b: { c: 3 } }

可以发现原来的对象和你所拷贝的对象的值会一起变化

深拷贝:

// 使用JSON方法(有局限性)
let original = { a: 1, b: { c: 2 } };
let deepCopy = JSON.parse(JSON.stringify(original));

deepCopy.b.c = 3;
console.log(original);      // 输出:{ a: 1, b: { c: 2 } }
console.log(deepCopy);      // 输出:{ a: 1, b: { c: 3 } }

也可以使用load库的

// 使用lodash库(需要先安装lodash)

// const _ = require('lodash');

// let deepCopy = _.cloneDeep(original);

可以发现原先的对象不会随着你所拷贝对象的变化而变化

手写一个深拷贝

//   深拷贝

function deepClone(obj, cache = new WeakMap()) {

  if (typeof obj !== 'object') return obj

  if (obj === null) return obj

  if (cache.get(obj)) return cache.get(obj) // 防止循环引用,程序进入死循环

  if (obj instanceof Date) return new Date(obj)

  if (obj instanceof RegExp) return new RegExp(obj)

  // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数

  let cloneObj = new obj.constructor()

  cache.set(obj, cloneObj) // 缓存拷贝的对象,用于处理循环引用的情况

  for (let key in obj) {

    if (obj.hasOwnProperty(key)) {

      cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝

    }

  }

  return cloneObj

}

const obj = { name: 'Jack', address: { x: 100, y: 200 } }

obj.a = obj // 循环引用

const newObj = deepClone(obj)

console.log(newObj.address === obj.address) // false

初步解析:

1.首先判断类型,基本类型,直接返回

2.复杂对象判断,处理null的逻辑

3.防止函数陷入无限引用

4.处理日期和正则表达式

这边用一个复杂对象来更好的帮助理解

const complexObj = {number: 123,string: 'Hello',date: new Date(),regex: /abc/gi,array: [1, 2, 3],nested: {boolean: true,nullValue: null,undef: undefined,nestedObj: {a: 1,b: [2, 3]}},circular: null // 将会在稍后设置循环引用
};

首先他一定是个对象,不是null date 正则什么的~

这边直接看到循环函数

  for (let key in obj) {

    if (obj.hasOwnProperty(key)) {

      cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝

    }

  }

其中hasOwnProperty是检查obj是否直接拥有该key,而不是从原型链继承下来的

返回用deepClone进行深拷贝,会进行cloneObj[number]的赋值,即deepClone()

比如例子的object的第一个key为[number],会进行cloneObj[key]的赋值=deepClone(obj[number],cache),其中obj[number]的值为123,!==objecet,会return 123

就可以cloneObj得到{number:123}

再遍历下一个key string,同理,直到key为nested的时候,检测到为object。会重复上边的势力,实现一个新的一模一样的实例

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

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

相关文章

NFT 智能合约实战-快速开始(1)NFT发展历史 | NFT合约标准(ERC-721、ERC-1155和ERC-998)介绍

文章目录 NFT 智能合约实战-快速开始(1)NFT发展历史国内NFT市场国内NFT合规性如何获得NFT?如何查询NFT信息?在 OpenSea 上查看我们的 NFT什么是ERC721NFT合约标准ERC-721、ERC-1155和ERC-998 对比ERC721IERC721.sol 接口内容关于合约需要接收 ERC721 资产 onERC721Received…

Nginx面试题精选及参考答案(3万字长文)

目录 什么是Nginx,它主要用于哪些场景? Nginx和Apache有什么区别? 描述一下Nginx的事件驱动模型。 Nginx如何处理静态文件和动态请求? 什么是反向代理,Nginx如何实现反向代理? 如何在Linux系统中安装Nginx? Nginx的主要配置文件有哪些? 如何修改Nginx的配置以实…

软考初级网络管理员_01_计算机系统基础知识(硬件)单选题

1.在字长为16位、32位、62位或128位的计算机中,字长为()位的计算机数据运算精度最高。 16 32 64 128 2.8位、16位、32位和64位字长的计算机中,()位字长计算机的数据运算精度最高。 9 8 16 64 3.声卡的性能指标主要包括-和采样位数:在采样位数分…

如何随机化列表中的元素?

一、技术难点 在Python中,随机化列表中的元素通常指的是对列表进行洗牌(shuffle)操作,即在不改变列表中元素数量的前提下,随机改变元素的顺序。这个过程看似简单,但在实际实现中需要考虑一些技术细节和难点…

插入排序(Insertion_sort)

最简单的一种排序 基本思想就是从第一个元素开始,每次排列一个元素,一直排列到结尾 例如: 3 1 4 5 7 2 6 第一个元素不用排序,从第二个开始 因为3 > 1所以直接将3覆盖到1上 3 3 4 5 7 2 6 而1用一个变量先…

【CMake】install用法

以前一直不清楚install的具体作用,现在明白了,其实就是把你的文件(生成的二进制,源代码或者任意)给复制(也可以说安装)到指定路径。 将二进制安装到Bin文件夹 比如我生成了一个test程序&#…

【教学类-64-02】20240610色块眼力挑战(二)-2-25宫格色差10-100(10倍)(星火讯飞)

背景需求 以下的色块眼里挑战需要人工筛选图片,非常繁琐。 【教学类-64-01】20240607色块眼力挑战(一)-0-255随机底色-CSDN博客文章浏览阅读446次,点赞12次,收藏5次。【教学类-64-01】20240607色块眼力挑战&#xff…

Linux安装Docker | 使用国内镜像

环境 CentOS7 先确认能够上网 curl www.baidu.com返回该输出说明网络OK 步骤一:安装gcc 和 gcc-c yum -y install gccyum -y install gcc-c步骤二:安装Docker仓库 yum install -y yum-utils接下来配置yum的国内镜像 yum-config-manager --add-re…

tomcat服务器之maxHttpHeaderSize

背景:在OA流程表单中,填写了200条数据,一提交,秒报400错误,且请求没有打到后端中(无报错日志),一开始以为是谷歌浏览器的问题,可百度上关于这个错误的解决方案都是清除缓…

转让北京劳务分包地基基础施工资质条件和流程

地基基础资质转让流程是怎样的?对于企业来说,资质证书不仅是实力的证明,更是获得工程承包的前提。而在有了资质证书后,企业才可以安心的准备工程投标,进而在工程竣工后获得收益。而对于从事地基基础工程施工的企业,需…

5、Spring之Bean生命周期~创建Bean(1)

5、Spring之Bean生命周期~创建Bean 创建BeanresolveBeanClass()方法doResolveBeanClass()方法 resolveBeforeInstantiation()方法 创建Bean Spring Bean的生命周期首先会经过扫描,然后回经过合并,合并之后就会通过getBean()方法去获取bean,ge…

特种设备起重机指挥题库附答案

1、【多选题】力的三要素是指:( )。(ACD) A、力的大小 B、力的单位 C、力的方向 D、力的作用点 2、【多选题】司索作业规范正确的要求是( )(ABC) A、吊点正确 B、吊索挂设合理 C、绑扎牢靠 D、吊索长短一致 3、【多选题】圆柱形物体兜吊时,一定要放空圈&#…

【python】python GUI编程--tkinter模块初探

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

归并排序(Merge_sort)

归并排序: 归并的意思是将两个数组合成为一个,而归并排序就是:将一个数组分为许多个,让多个数组按大小归并,直到归并为一个; 基本思想为: 将一个数组拆分为许多个两两结合的数组,…

树的4种遍历

目录 树的四种遍历方式的总结 1. 前序遍历(Pre-order Traversal) 2. 中序遍历(In-order Traversal) 3. 后序遍历(Post-order Traversal) 4. 层序遍历(Level-order Traversal 或 广度优先遍…

引入别人的安卓项目报错

buildscript { repositories { google() jcenter() } dependencies { classpath com.android.tools.build:gradle:4.1.0 // 使用最新版本的插件 } } allprojects { repositories { google() jcenter() } } 在…

Feign是如何发送http请求的底层源码

Feign 的底层源码涉及多个组件和库来实际发送 HTTP 请求。Feign 的主要目标是提供一个声明式的 Web Service 客户端接口,而底层实现则依赖于其他库(如 OkHttp、Apache HttpClient 等)来发送实际的 HTTP 请求。 1、接口代理 当你通过 Feign …

Keil软件仿真的使用

一、软件的初始化设置 初始设置可以按照下图,这里我使用的是STM32F103C8T6,所以单片机型号为STM32F103C8,这个设置在Debug目录下。然后进行时钟的设置,我们板上晶振为8M,这里将时钟改为8. 或许有人想问如果是别的型号单…

Effective Java 1 用静态工厂方法代替构造器

知识点上本书需要会Java语法和lang、util、io库,涉及concurrent和function包。 内容上主要和设计模式相关,代码风格力求清晰简洁,代码尽量复用,组件尽量少依赖,错误尽早发现。 第1个经验法则:用静态工厂方…

Chroium 源码目录结构分析(1):源码目录体积一栏

获取源码 首先,我们拉一份最新的源代码(笔者是2024.6.6日拉取的): fetch --nohistory chromium 源码预处理 如果运行build,会生成许多生成的代码,因此我们不运行build。 然后,把干扰后续分析…