js-17-对数组、对象进行浅拷贝和深拷贝
目录
- 数组
- 一、浅拷贝
- 1. 展开运算符...
- 2. Array.prototype.slice()
- 二、深拷贝
- 1. JSON方法
- 2. 递归函数
- 对象
- 一、浅拷贝
- 1. Object.assign()
- 2. 展开运算符...
- 二、深拷贝
- 1. JSON方法
- 2. 递归函数
自己总结的一些方法,可能有不到位的地方,欢迎指出
数组
一、浅拷贝
1. 展开运算符…
let arr1 = [1,2,'3',true, { name: '李华'}]
let arr2 = [...arr1] // arr2=[1,2,'3',true, { name: '李华'}]arr2[0] = 0 // 修改浅拷贝数组中的基本类型元素,原始数组不受影响
arr2[3] = false // 修改浅拷贝数组中的基本类型元素,原始数组不受影响
arr2[4].name = '小帅' // 修改浅拷贝数组中的对象的属性,由于对象是引用类型,所以原始数组中的对象也会受到影响console.log(arr1) // [1,2,'3',true, { name: '小帅'}]
console.log(arr2) // [0,2,'3',false,{ name: '小帅'}]
2. Array.prototype.slice()
let arr1 = [1, 2, '3', true, { name: '李华'}]
let arr2 = arr1.slice() // arr2=[1,2,'3',true,{ name: '李华'}]arr2[0] = 0
arr2[3] = false
arr2[4].name = '小帅'console.log(arr1) // [1, 2, '3', true, { name: '小帅' }]
console.log(arr2) // [0, 2, '3', false, { name: '小帅' }]
二、深拷贝
1. JSON方法
注意:此方法不能处理函数、undefined、Symbol和循环引用
let arr1 = [1, 2, '3', true, { name: '李华'}]let arr2 = JSON.parse(JSON.stringify(arr1))arr2[0] = 0arr2[3] = falsearr2[4].name = '小帅'console.log(arr1) // [1, 2, '3', true, { name: '李华'}]console.log(arr2) // [0, 2, '3', false, { name: '小帅'}]
2. 递归函数
function deepClone(obj, hash = new WeakMap()) {if (obj === null) return nullif (obj instanceof Date) return new Date(obj) // 如果是日期对象,则直接返回一个新的日期对象if (obj instanceof RegExp) return new RegExp(obj) // 如果是正则对象,则直接返回一个新的正则对象// 如果循环引用了就用 weakMap 来解决 if (hash.has(obj)) return hash.get(obj);let allDesc = Object.getOwnPropertyDescriptors(obj);let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);hash.set(obj, cloneObj);for (let key of Reflect.ownKeys(obj)) {if (typeof obj[key] === 'object' && obj[key] !== null) {cloneObj[key] = deepClone(obj[key], hash); // 递归复制 } else {cloneObj[key] = obj[key];}}return cloneObj;}let arr1 = [1, 2, '3', true, { name: '李华' }, undefined]let arr2 = deepClone(arr1)arr2[4].name = '小帅'console.log(arr1) // [1, 2, '3', true, { name: '李华' }, undefined]console.log(arr2) // [1, 2, '3', true, { name: '小帅' }, undefined]
对象
一、浅拷贝
1. Object.assign()
let obj1 = {a: 1, b: {c: 2}}let obj2 = Object.assign({}, obj1) // obj2={a:1, b: {c:2}}obj2.a = 100obj2.b.c = 200console.log(obj1) // { a: 1, b: { c: 200 } }console.log(obj2) // { a: 100, b: { c: 200 } }
2. 展开运算符…
let obj1 = {a: 1, b: {c: 2}}let obj2 = {...obj1}obj2.a = 100obj2.b.c = 200console.log(obj1) // { a: 1, b: { c: 200 } }console.log(obj2) // { a: 100, b: { c: 200 } }
二、深拷贝
1. JSON方法
let obj1 = {a: 1,b: {c: 2},d: [3, 4],e: undefined, // 注意此方法undefined不会被复制f: function(){ console.log('Hello world')} // 注意此方法函数不会被复制}let obj2 = JSON.parse(JSON.stringify(obj1))// console.log(obj2) // {a:1, b: {c:2}, d: [3,4]}obj2.b.c = 200obj2.d[0] = 300console.log(obj1) // { a: 1, b: { c: 2 }, d: [3, 4], e: undefined, f: f()}console.log(obj2) // { a: 1, b: { c: 200 }, d: [300, 4] }
2. 递归函数
function deepClone(obj, hash = new WeakMap()) {// 处理基本数据类型和null if (obj === null || typeof obj !== 'object') {return obj;}// 处理日期和正则对象 if (obj instanceof Date) {return new Date(obj);}if (obj instanceof RegExp) {return new RegExp(obj);}// 如果已经处理过这个对象,则直接返回缓存的结果 if (hash.has(obj)) {return hash.get(obj);}// 根据obj的类型创建一个新的对象或数组 let cloneObj = Array.isArray(obj) ? [] : {};hash.set(obj, cloneObj); // 将原始对象和克隆对象存储在hash中,以处理循环引用 // 递归复制对象的每个属性 for (let key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = deepClone(obj[key], hash);}}// 如果obj是Map或Set,则需要特殊处理 if (obj instanceof Map) {cloneObj = new Map();obj.forEach((value, key) => {cloneObj.set(deepClone(key, hash), deepClone(value, hash));});} else if (obj instanceof Set) {cloneObj = new Set();obj.forEach(value => {cloneObj.add(deepClone(value, hash));});}return cloneObj;}let obj1 = {a: 1,b: {c: 2},d: [3, 4],e: undefined, // 注意此方法undefined不会被复制f: function () { console.log('Hello world') } // 注意此方法函数不会被复制,而且其实通常不深拷贝函数}let obj2 = deepClone(obj1)// console.log(obj2) // { a: 1, b: { c: 2 }, d:[3, 4], e:undefined, f:f()}obj2.b.c = 200obj2.d[0] = 300console.log(obj1) // { a: 1, b: { c: 2 }, d: [3, 4], e: undefined, f: f()}console.log(obj2) // { a: 1, b: { c: 200 }, d: [300, 4], e: undefined, f: f() }
相关文章:
js-17-对数组、对象进行浅拷贝和深拷贝
目录 数组一、浅拷贝1. 展开运算符...2. Array.prototype.slice() 二、深拷贝1. JSON方法2. 递归函数 对象一、浅拷贝1. Object.assign()2. 展开运算符... 二、深拷贝1. JSON方法2. 递归函数 自己总结的一些方法,可能有不到位的地方,欢迎指出 数组 一、…...
Ubuntu24.04中安装Electron
1. 安装Nodejs 使用代理服务从github下载并执行Nodejs安装脚本(假设代理服务器为192.168.2.150:10792) curl -x 192.168.2.150:10792 -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash #注意,Nodejs官网的安装命令少了下面这一行: …...
CPU中也应用到了缓存:CPU3层高速缓存,以及它的缓存一致性问题、MESI协议和Java的一些应用
为什么需要cpu高速缓存? 缓存,一般是为了用来协调两端的数据传输效率差(也可以归纳为性能差),提升响应速度。那么CPU的高速缓存是用来协调什么之间的速度差呢? CPU在处理一条指令的时候,会读写…...
如何使用开发者工具捕获鼠标右键点击事件
要使用浏览器的开发者工具捕获鼠标右键点击事件,请按照以下步骤操作: 打开开发者工具 在大多数浏览器中,您可以按 F12 键或右键单击页面并选择"检查"或"检查元素"。 切换到 Console 标签页 在开发者工具中,找到并点击 “Console” 标签。 添加事件监听器…...
【几何】个人练习-Leetcode-1453. Maximum Number of Darts Inside of a Circular Dartboard
题目链接:https://leetcode.cn/problems/maximum-number-of-darts-inside-of-a-circular-dartboard/description/ 题目大意:给出一系列点和一个圆的半径,(寻找一个圆心)求这个半径的圆最多能覆盖多少个点。 思路&…...
啤酒:从饮品到文化的演变
在人类饮品的长河中,啤酒以其不同的魅力走过了一段漫长的历史旅程。它不仅仅是一种简单的饮品,更是一种文化的象征,一种生活的态度。今天,我们将一起追溯啤酒从单一的饮品到丰富文化的演变过程,并感受Fendi Club精酿啤…...
Java 中 Map 常用类和数据结构详解
1. 引言 在Java编程中,Map是一种重要的数据结构,广泛应用于各种场景,Map实现了键值对(key-value)的存储方式,使得开发者能够快速检索、更新和操作数据。本篇文章将详细讲解Java中常用的Map类及其底层数据结…...
实时监控,动态调整 —— 淘宝商品详情API助力商家实现灵活经营
在讨论实时监控和动态调整的策略时,虽然我不能直接提供淘宝商品详情API的具体代码(因为这通常涉及商业机密和API密钥等敏感信息),但我可以给出一个概念性的示例,说明如何使用这类API来辅助商家实现灵活经营。 概念性示…...
WebGL常用接口和事件
目录 初始化WebGL上下文清除缓冲区缓冲区对象着色器和程序属性指针渲染事件监听错误处理纹理映射...
Golang | Leetcode Golang题解之第429题N叉树的层序遍历
题目: 题解: func levelOrder(root *Node) (ans [][]int) {if root nil {return}q : []*Node{root}for q ! nil {level : []int{}tmp : qq nilfor _, node : range tmp {level append(level, node.Val)q append(q, node.Children...)}ans append(a…...
数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式
数据库的全透明加密和半透明加密主要是针对数据存储安全的不同处理方式。 全透明加密(也称作无损加密或自动加密)就像是给文字戴上了一层无形的面具。在用户看来,他们在数据库中输入的是明文(比如姓名、密码)…...
MySQL的登录、访问、退出
一、登录: 访问MySQL服务器对应的命令:mysql.exe ,位置:C:\Program Files\MySQL\MySQL Server 8.0\bin (mysql.exe需要带参数执行,所以直接在图形界面下执行该命令会自动结束) 执行mysql.exe命令的时候出…...
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-25 1. PromSec: Prompt Optimization for Secure Generation of Functional Source Code with Large Language Models (LLMs) M Nazzal, I Khalil, A Khreishah, NH Phan - arXiv preprint arXiv:2409.12699, 2…...
PyTorch框架安装
安装 pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple 介绍 PyTorch 一个 Python 深度学习框架,它将数据封装成张量(Tensor)来进行处理。 PyTorch 中的张量就是元素为 同一种数据 类型的多维矩阵。在 PyTorch 中࿰…...
分布式锁优化之 使用lua脚本改造分布式锁保证判断和删除的原子性(优化之LUA脚本保证删除的原子性)
文章目录 1、lua脚本入门1.1、变量:弱类型1.2、流程控制1.3、在lua中执行redis指令1.4、实战:先判断是否自己的锁,如果是才能删除 2、AlbumInfoApiController --》testLock()3、AlbumInfoServiceImpl --》testLock() 1、lua脚本入门 Lua 教程…...
从安防视频监控行业发展趋势看EasyCVR平台如何驱动行业智能升级
一、市场规模持续增长 随着科技的进步和社会安全意识的提升,安防视频监控行业市场规模持续增长。据市场研究数据显示,全球智能视频监控市场规模已超过千亿美元,并有望在未来几年内保持高速增长。在中国市场,随着智慧城市、工业互…...
TIOBE 编程指数 9 月排行榜公布 VB.Net第七
原文地址:百度安全验证 IT之家 9 月 8 日消息,TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标,评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎,今天 TIOBE 官网公布了 2024 年 9 月的编程语言排行榜…...
如何用ChatGPT制作一款手机游戏应用
有没有想过自己做一款手机游戏,并生成apk手机应用呢?有了人工智能,这一切就成为可能。今天,我们就使用ChatGPT来创建一个简单的井字棋游戏(Tic-Tac-Toe),其实这个过程非常轻松且高效。 通过Cha…...
0基础学前端 day4
大家好,欢迎来到无限大的频道。 今天继续带领大家开始0基础学前端。 一、 什么是Bootstrap框架? Bootstrap是一个开源前端框架,于2011年由Twitter的开发团队开发并发布。其主要目的是简化开发过程,并使开发者能够轻松快速地构建…...
功能测试详解
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、测试项目启动与研读需求文档 (一) 组建测试团队 1、测试团队中的角色 2、测试团队的基本责任 尽早地发现软件程序、系统或产品中所…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
