讲清楚浅拷贝和深拷贝
先放出实现浅拷贝和深拷贝的一些方法(直接食用):
1.浅拷贝:
浅拷贝在拷贝对象的时候,对于对象最外一层实现的是普通的值拷贝,对于对象里面的对象是浅拷贝,只复制地址不复制地址对应的值。
/* 方法1.1:扩展运算符(最简单的方式)
*/
const originalObject = { a: 1, b: 2, c: {d: 3} };
const shallowCopy = { ...originalObject };originalObject.a = 10;
console.log(originalObject.a); // 输出 10
console.log(shallowCopy.a); // 输出 1originalObject.c.d = 11;
console.log(shallowCopy.c.d); // 输出 11
console.log(originalObject.c.d); // 输出 11
/* 方法2:Object.assign()
*/
const originalObject = { a: 1, b: 2, c: { d: 3} };
const shallowCopy = Object.assign({}, originalObject);
originalObject.a = 10;
originalObject.c.d = 11;console.log(originalObject.a); // 输出 10
console.log(shallowCopy.a); // 输出 1
console.log(originalObject.c.d); // 输出 11
console.log(shallowCopy.c.d); // 输出 11
/* 方法1.3:自定义函数实现浅拷贝
*/
function shallowCopyFun(obj) {// 只拷贝对象if (typeof obj !== 'object' || obj === null) {return obj;}// 根据 obj 的类型决定新对象是数组还是对象let newObj = Array.isArray(obj) ? [] : {};// 遍历 obj,并复制其自身属性到新对象for (let key in obj) {if (obj.hasOwnProperty(key)) {newObj[key] = obj[key];}}return newObj;
}
const originalObject = { a: 1, b: 2, c: { d: 3,e: 4 } };
const shallowCopy = shallowCopyFun(originalObject);originalObject.a = 10;
console.log(shallowCopy.a); // 输出 1
console.log(originalObject.a); // 输出 10originalObject.c.d = 11;
console.log(shallowCopy.c.d); // 输出 11
console.log(originalObject.c.d); // 输出 11
2.深拷贝
/* 方法2.1:Json对象实现深拷贝JSON 序列化和反序列化
*/
const originalObject = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(originalObject));originalObject.b.c = 10;
console.log(originalObject.b.c); // 输出 10
console.log(deepCopy.b.c); // 输出 2
/* 方法2.2:递归函数实现
*/
function deepCopyFun(obj) {// 检查值是否是引用类型if (typeof obj !== "object" || obj === null) {return obj;}if (obj instanceof Date) {return new Date(obj);}if (obj instanceof RegExp) {return new RegExp(obj.source, obj.flags);}if (obj instanceof Function) {return obj;}// 初始化一个新的数组或对象let newObj = Array.isArray(obj) ? [] : {};for (let key in obj) {// 确保属性属于对象本身,不是继承的if (obj.hasOwnProperty(key)) {// 递归复制每个属性newObj[key] = deepCopyFun(obj[key]);}}return newObj;
}
const originalObject = { a: 1, b: { c: 2 } };
const deepCopy = deepCopyFun(originalObject);originalObject.b.c = 10;
console.log(originalObject.b.c); // 输出 10
console.log(deepCopy.b.c); // 输出 2
/* 方法2.3:concat实现深拷贝concat(arr1, arr2,...)
*/
var arr = [1,2,3]
var newArr = [].concat(arr)
arr.push(4)
console.log('arr:👉', arr);
console.log('newArr:👉', newArr);
/* arr:👉 [ 1, 2, 3, 4 ]newArr:👉 [ 1, 2, 3 ]
*/
/* 方法2.4:slice实现深拷贝slice(idx1, idx2)
*/
var arr = [1,2,3]
var newArr = arr.slice()
arr.push(4)
console.log('arr:👉', arr);
console.log('newArr:👉', newArr);
/* arr:👉 [ 1, 2, 3, 4 ]newArr:👉 [ 1, 2, 3 ]
*/
/* 方法2.5:lodash实现深拷贝_.cloneDeep(value)
value : 要深拷贝的值。
返回拷贝后的值
vue 中使用 :a. npm i --save lodash 下载依赖b. import _ from 'lodash' 在 组件 中引入 c. 用法和下面的一样
*/
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false
/* 方法2.6:扩展符实现深拷贝
*/
var a=[1,2,3]
var b=[...a];
b.push(4);
console.log(b);//1,2,3,4
console.log(a)//1,2,3
为什么会有浅拷贝和深拷贝?这要从javaScript数据类型说起。分为基本数据类型和引用数据类型。
-
基本类型数据都是按照值访问的,直接保存和修改在变量里面实际的值。
值类型:在存储变量中存储的是值的本身,因此叫做值类型,即
string,Number,Boolean,Undefined,Null其中,基本数据类型null返回的是一个空的对象object,如果有一个变量我们以后打算存储为对象,默认值可以设置成null。 -
引用类型数据是按照引用访问的,即保存在变量对象中的是一个地址,该地址与堆内存的实际值相关联。
引用数据类型在存储变量中存储的仅仅是地址(引用),因此叫做引用数据类型。即通过
new关键字创建的对象(系统对象、自定义对象),如Object、Array、Date等。
操作系统控制栈,但是它不控制堆。具体堆栈理解可以自行bing!
-
引用类型的值是同时保存在栈内存和堆内存中的对象
javascript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间,那我们操作啥呢? 实际上,是操作对象的引用, 所以引用类型的值是按引用访问的。 准确地说,引用类型的存储需要内存的栈区和堆区(堆区是指内存里的堆内存)共同完成,栈区内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。 -
基本数据类型-在百度上大多数都是说存在栈中的。从知乎回答找到正确答案link。即:
字符串: 存在堆里,栈中为引用地址,如果存在相同字符串,则引用地址相同。
数字: 小整数存在栈中,其他类型存在堆中。
其他类型:引擎初始化时分配唯一地址,栈中的变量存的是唯一的引用。
所以这里我们在来说说深拷贝和浅拷贝的区别:
- 浅拷贝:只复制指向某个对象的指针,而不是复制对象本身,新旧对象共享一块内存。
- 深拷贝:复制并创建一个一模一样的对象,不共享内存,修改新的对象,旧对象保持不变。
相关文章:
讲清楚浅拷贝和深拷贝
先放出实现浅拷贝和深拷贝的一些方法(直接食用): 1.浅拷贝: 浅拷贝在拷贝对象的时候,对于对象最外一层实现的是普通的值拷贝,对于对象里面的对象是浅拷贝,只复制地址不复制地址对应的值。 /* 方法1.1:扩…...
[足式机器人]Part2 Dr. CAN学习笔记- 最优控制Optimal Control Ch07
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记 - 最优控制Optimal Control Ch07-1最优控制问题与性能指标 1. 最优控制问题与性能指标2. 动态规划 Dynamic Programming2.1 基本概念2.2 代码详解2.3 简单一维案例 3. 线性二次型调节器ÿ…...
RedisInsight详细安装教程
简介 RedisInsight 是一个直观高效的 Redis GUI 管理工具,它可以对 Redis 的内存、连接数、命中率以及正常运行时间进行监控,并且可以在界面上使用 CLI 和连接的 Redis 进行交互(RedisInsight 内置对 Redis 模块支持)。 RedisIn…...
maven组件升级报错经验汇总
1. NosuchMethodError org.springframework.beans.factory.support.genericBeanDefinition(xxxxx) 2. ClassNotFoundException: org.springframework.boot.SpringApplication 可能冲突的依赖是: <dependency><groupId>org.springframework.boot</g…...
JS 中的 async 与 await
课程地址 有 4 个返回 Promise 对象的函数 ABCD,现在想让这 4 个 Promise 顺序执行: const isA true; const isB true; const isC true; const isD true;function A() {return new Promise((resolve, reject) > {console.log("running A&q…...
SQL 系列教程(六)
目录 SQL FOREIGN KEY 约束 SQL FOREIGN KEY 约束 创建表时的 FOREIGN KEY 约束 修改表时的 FOREIGN KEY 约束 撤销 FOREIGN KEY 约束 SQL CHECK 约束 SQL CHECK 约束 创建表时的 CHECK 约束 修改表的 CHECK 约束 撤销 CHECK 约束 SQL DEFAULT 约束 SQL DEFAULT 约…...
CocoaPods的安装和使用
前言 本篇文章讲述CocoaPods的安装和使用 安装cocoaPods 如果电脑没有安装过cocoaPods,需要先安装,使用下面的命令: sudo gem install cocoapods输入密码后开始安装,需要等待。。。但是我这里报错了。 The last version of d…...
Linux下软件安装的命令【RPM,YUM】及常用服务安装【JDK,Tomcat,MySQL】
Linux下软件安装的命令 源码安装 以源代码安装软件,每次都需要配置操作系统、配置编译参数、实际编译,最后还要依据个人喜好的方式来安装软件。这个过程很麻烦很累人。 RPM软件包管理 RPM安装软件的默认路径: 注意: /etc 配置文件放置目录…...
【linux】-telnet服务安装
1. 说明 telnet 分为 :telnet 服务端 和 telnet 客户端 本文只演示安装 telnet服务端 2. 安装telnet服务端、以及守护服务xinetd 2.1 检测telnet-server的rpm包是否安装 rpm -qa telnet-server 2.2 若未安装,则安装telnet-server࿰…...
安卓开发——Activity及常用布局和控件的使用
Activity及常用布局和控件的使用 一、实验目的 掌握Android常用布局和控件的使用。 Activity组件使用和Intent机制,加强对Activity生命周期的理解 二、实验设备及器件 Android Studio,图标:http://10.37.59.210/download/icon/MobileShopI…...
.net访问oracle数据库性能问题
问题: 生产环境相同的inser语句在别的非.NET程序相应明显快于.NET程序,执行时间相差比较大,影响正常业务运行,测试环境反而正常。 问题详细诊断过程 问题初步判断诊断过程: 查询插入慢的sql_id 检查对应的执行计划…...
vue上传解析excel表格并修改字段名
目录 1.安装 xlsx 2.引入 3.使用 1.安装 xlsx npm install xlsx 2.引入 import * as XLSX from xlsx; 3.使用 <template><div class"UploadCptOutbox"><div class"Tooloutbox"><el-uploadclass"upload"ref"u…...
jupyter notebook删除kernel & conda 删除虚拟环境
jupyter kernelspec list #列出jupyter的所有kernel jupyter kernelspec remove kernel_name #删除特定的kerneljupyter kernelspec list 命令可以在任何激活的环境中运行,无论是 base 环境还是某个虚拟环境。该命令将列出所有已注册的 Jupyter 内核,包括…...
Redis在生产环境中可能遇到的问题与解决方案(三)
11. Redis高可用问题 问题描述 在Redis集群中,当主节点发生故障时,需要快速切换到备用主节点,确保系统高可用。 解决方案 Redis Sentinel: 使用Redis Sentinel进行主从节点的监控和自动故障转移。 备用主节点: 配置…...
【C++干货铺】 RAII实现智能指针
个人主页点击直达:小白不是程序媛 C系列专栏:C干货铺 代码仓库:Gitee 目录 为什么需要智能指针? 内存泄漏 什么是内存泄漏,内存泄露的危害 内存泄漏的分类 堆内存泄漏(Heap leak) 系统资…...
【竞技宝jjb.lol】LOL:xiaohu岩雀天命抢龙扭转乾坤 WBG2-0轻取RA
北京时间2024年1月26日,英雄联盟LPL2024春季赛在昨天迎来第一周第四个比赛日,本日首场比赛由WBG对阵RA。本场比赛RA虽然在首局前期给了WBG很大的压力,但WBG还是凭借后期出色的团战配合拿下胜利,最终WBG2-0轻取RA。以下是本场比赛的…...
GoZero微服务个人探究之路(九)api文件编写总结
参考来源go-zero官方文档https://go-zero.dev/docs/tutorials 前言 go-zero是目前star最多的go语言微服务框架,api 是 go-zero特殊的语言,类型文件,go-zero自带的goctl可以通过.api文件生成http服务代码 api文件内容编写 不可使用关键字 …...
泛型..
1.泛型 所谓泛型 在类定义处是一种类型参数(我们平常所见到的参数指的就是方法中的参数 他接收有外界传递来的值 然后在方法中进行使用) 在类内部的话 则充当一种占位符 并且还提高了代码的复用率 何以见得提高了代码的复用率 其实就是通过对比使用了泛型技术和没有使用泛型技…...
Android App开发基础(1)—— App的开发特点
本文介绍基于Android系统的App开发常识,包括以下几个方面:App开发与其他软件开发有什么不一样,App工程是怎样的组织结构又是怎样配置的,App开发的前后端分离设计是如何运作实现的,App的活动页面是如何创建又是如何跳转…...
docker-compose初探
我一直直接使用docker命令来创建容器,没有怎么用过docker-compose。也不知道docker-compose和docker有什么区别,docker-compose有什么好处。 现在我约略认为,docker-compose是一个简化docker命令的工具,或者说,它是能…...
如何用PPTist快速创建专业演示文稿:免费在线PPT制作完全指南
如何用PPTist快速创建专业演示文稿:免费在线PPT制作完全指南 【免费下载链接】PPTist 基于 Vue3.x TypeScript 的在线演示文稿(幻灯片)应用,还原了大部分 Office PowerPoint 常用功能,实现在线PPT的编辑、演示。支持导…...
UReport2实战:如何优雅地导出多Sheet页报表(动态/静态分页全解析)
UReport2实战:如何优雅地导出多Sheet页报表(动态/静态分页全解析) 在数据驱动的商业环境中,报表导出功能已成为企业级应用的标配需求。当面对海量数据时,传统的单Sheet页Excel导出方案往往导致文件臃肿、查阅困难。URe…...
GLM-OCR模型安装包制作:将模型与服务打包成可执行文件
GLM-OCR模型安装包制作:将模型与服务打包成可执行文件 你是不是也遇到过这样的情况?自己好不容易把一个AI模型跑起来了,效果也不错,想分享给同事或者朋友用用,结果对方光是配环境、装依赖就折腾了半天,最后…...
nli-distilroberta-base实战案例:企业知识库问答系统中的逻辑一致性校验
nli-distilroberta-base实战案例:企业知识库问答系统中的逻辑一致性校验 1. 项目概述 在构建企业知识库问答系统时,确保回答与问题之间的逻辑一致性是一个关键挑战。nli-distilroberta-base是基于DistilRoBERTa模型的自然语言推理(NLI)服务,…...
终极风扇控制指南:如何用FanControl 264版彻底告别电脑噪音烦恼
终极风扇控制指南:如何用FanControl 264版彻底告别电脑噪音烦恼 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Tr…...
OpCore-Simplify:智能化解构OpenCore EFI配置难题,让黑苹果安装不再复杂
OpCore-Simplify:智能化解构OpenCore EFI配置难题,让黑苹果安装不再复杂 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为…...
浏览器自动化:OpenClaw+GLM-4.7-Flash爬取数据并生成报告
浏览器自动化:OpenClawGLM-4.7-Flash爬取数据并生成报告 1. 为什么选择OpenClaw做浏览器自动化? 去年我接手了一个每周都要重复的数据分析任务:登录内部系统导出销售数据,清洗后生成可视化报告。这种机械劳动不仅耗时࿰…...
2. Linux桌面环境介绍
2. Liunx桌面环境介绍 桌面介绍终端设置 设置终端属性:字体快捷键: 新建终端(ctrlaltN)新建标签(ctrlaltT)背景和锁屏设置语言和输入法设置课后作业 系统开机、关机账户的注销、锁屏打开常用程序࿰…...
轻量级二维码工具性能优化:从加载到部署的全流程实践
轻量级二维码工具性能优化:从加载到部署的全流程实践 【免费下载链接】qrcodejs Cross-browser QRCode generator for javascript 项目地址: https://gitcode.com/gh_mirrors/qr/qrcodejs 二维码生成功能已成为现代Web应用的常见需求,但传统实现方…...
OpenClaw成本优化方案:ollama GLM-4.7-Flash自建模型接口实践
OpenClaw成本优化方案:ollama GLM-4.7-Flash自建模型接口实践 1. 为什么需要关注OpenClaw的token消耗问题 第一次用OpenClaw完成自动化周报任务时,我盯着账单倒吸一口凉气——生成三份周报竟然消耗了接近15万token。这让我意识到,如果不解决…...
