讲清楚浅拷贝和深拷贝
先放出实现浅拷贝和深拷贝的一些方法(直接食用):
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命令的工具,或者说,它是能…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...