当前位置: 首页 > news >正文

讲清楚浅拷贝和深拷贝

先放出实现浅拷贝和深拷贝的一些方法(直接食用):

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关键字创建的对象(系统对象、自定义对象),如ObjectArrayDate等。

操作系统控制栈,但是它不控制堆。具体堆栈理解可以自行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. 线性二次型调节器&#xff…...

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 可能冲突的依赖是&#xff1a; <dependency><groupId>org.springframework.boot</g…...

JS 中的 async 与 await

课程地址 有 4 个返回 Promise 对象的函数 ABCD&#xff0c;现在想让这 4 个 Promise 顺序执行&#xff1a; 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&#xff0c;需要先安装&#xff0c;使用下面的命令&#xff1a; sudo gem install cocoapods输入密码后开始安装&#xff0c;需要等待。。。但是我这里报错了。 The last version of d…...

Linux下软件安装的命令【RPM,YUM】及常用服务安装【JDK,Tomcat,MySQL】

Linux下软件安装的命令 源码安装 以源代码安装软件&#xff0c;每次都需要配置操作系统、配置编译参数、实际编译&#xff0c;最后还要依据个人喜好的方式来安装软件。这个过程很麻烦很累人。 RPM软件包管理 RPM安装软件的默认路径: 注意&#xff1a; /etc 配置文件放置目录…...

【linux】-telnet服务安装

1. 说明 telnet 分为 &#xff1a;telnet 服务端 和 telnet 客户端 本文只演示安装 telnet服务端 2. 安装telnet服务端、以及守护服务xinetd 2.1 检测telnet-server的rpm包是否安装 rpm -qa telnet-server 2.2 若未安装&#xff0c;则安装telnet-server&#xff0…...

安卓开发——Activity及常用布局和控件的使用

Activity及常用布局和控件的使用 一、实验目的 掌握Android常用布局和控件的使用。 Activity组件使用和Intent机制&#xff0c;加强对Activity生命周期的理解 二、实验设备及器件 Android Studio&#xff0c;图标&#xff1a;http://10.37.59.210/download/icon/MobileShopI…...

.net访问oracle数据库性能问题

问题&#xff1a; 生产环境相同的inser语句在别的非.NET程序相应明显快于.NET程序&#xff0c;执行时间相差比较大&#xff0c;影响正常业务运行&#xff0c;测试环境反而正常。 问题详细诊断过程 问题初步判断诊断过程&#xff1a; 查询插入慢的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 命令可以在任何激活的环境中运行&#xff0c;无论是 base 环境还是某个虚拟环境。该命令将列出所有已注册的 Jupyter 内核&#xff0c;包括…...

Redis在生产环境中可能遇到的问题与解决方案(三)

11. Redis高可用问题 问题描述 在Redis集群中&#xff0c;当主节点发生故障时&#xff0c;需要快速切换到备用主节点&#xff0c;确保系统高可用。 解决方案 Redis Sentinel&#xff1a; 使用Redis Sentinel进行主从节点的监控和自动故障转移。 备用主节点&#xff1a; 配置…...

【C++干货铺】 RAII实现智能指针

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 为什么需要智能指针&#xff1f; 内存泄漏 什么是内存泄漏&#xff0c;内存泄露的危害 内存泄漏的分类 堆内存泄漏&#xff08;Heap leak&#xff09; 系统资…...

【竞技宝jjb.lol】LOL:xiaohu岩雀天命抢龙扭转乾坤 WBG2-0轻取RA

北京时间2024年1月26日&#xff0c;英雄联盟LPL2024春季赛在昨天迎来第一周第四个比赛日&#xff0c;本日首场比赛由WBG对阵RA。本场比赛RA虽然在首局前期给了WBG很大的压力&#xff0c;但WBG还是凭借后期出色的团战配合拿下胜利&#xff0c;最终WBG2-0轻取RA。以下是本场比赛的…...

GoZero微服务个人探究之路(九)api文件编写总结

参考来源go-zero官方文档https://go-zero.dev/docs/tutorials 前言 go-zero是目前star最多的go语言微服务框架&#xff0c;api 是 go-zero特殊的语言&#xff0c;类型文件&#xff0c;go-zero自带的goctl可以通过.api文件生成http服务代码 api文件内容编写 不可使用关键字 …...

泛型..

1.泛型 所谓泛型 在类定义处是一种类型参数(我们平常所见到的参数指的就是方法中的参数 他接收有外界传递来的值 然后在方法中进行使用) 在类内部的话 则充当一种占位符 并且还提高了代码的复用率 何以见得提高了代码的复用率 其实就是通过对比使用了泛型技术和没有使用泛型技…...

Android App开发基础(1)—— App的开发特点

本文介绍基于Android系统的App开发常识&#xff0c;包括以下几个方面&#xff1a;App开发与其他软件开发有什么不一样&#xff0c;App工程是怎样的组织结构又是怎样配置的&#xff0c;App开发的前后端分离设计是如何运作实现的&#xff0c;App的活动页面是如何创建又是如何跳转…...

docker-compose初探

我一直直接使用docker命令来创建容器&#xff0c;没有怎么用过docker-compose。也不知道docker-compose和docker有什么区别&#xff0c;docker-compose有什么好处。 现在我约略认为&#xff0c;docker-compose是一个简化docker命令的工具&#xff0c;或者说&#xff0c;它是能…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...