js中的 赋值 浅拷贝 和 深拷贝 详细解读

js数据类型主要分基本数据类型和引用数据类型。前者包括Number,String等,后者主要是Object,因此以下会针对不同的数据类型来分析,需要的朋友可以参考一下

基本数据类型(Primary Data Types):

  • String(字符串)

  • Number(数字)

  • Boolean(布尔值)

  • Null(空值)

  • Undefined(未定义)

  • Symbol(符号,ES6 新增)

  • BigInt(大整数,ES2020 新增)

引用数据类型(Reference Data Types):

  • Object(对象)

  • Array(数组)

  • Function(函数)

  • Date(日期)

  • RegExp(正则表达式)

  • Map(映射)

  • Set(集合)

  • WeakMap(弱映射)

  • WeakSet(弱集合)

前言:在学习下面文章前我们简单了解一下的内存的知识,以下先简要提一下

1、js内存

js内存,或者说大部分语言的内存都分为栈和堆。基本数据类型的变量值分配在栈上,引用数据类型的变量值分配在堆上,栈中只是存储具体堆中对象的地址。

(1)基本类型:
5种基本数据类型Undefined、Null、Boolean、Number 和 String,变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。

(2)引用类型:
存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

JavaScript存储对象都是存地址的,所以浅拷贝会导致 obj1 和obj2 指向同一块内存地址。改变了其中一方的内容,都是在原来的内存上做修改会导致拷贝对象和源对象都发生改变,而深拷贝是开辟一块新的内存地址,将原对象的各个属性逐个复制进去。对拷贝对象和源对象各自的操作互不影响。

2、赋值

对于基本数据类型,赋值操作是拷贝,即新旧变量不会相互影响。

  let a = 1let b = ab = 2console.log(a) // 1console.log(b) // 2

对于引用数据类型,赋值操作只是在栈中新增一个指向堆中对象的变量,即复制引用地址。新旧变量之间会互相影响,即在新变量上改变对象值,旧变量对应值也会改变。

  let a = {name: "mike"}let b = ab.name = "jack"console.log(a) // {name: "jack"}

3、浅拷贝

对于基本数据类型和不具有嵌套对象的数据,均是拷贝操作,新旧变量之间不会相互影响。

  let a = {name: "mike"}let b = {}b.name = a.nameb.name = "jack"console.log(a) // {name: "mike"}

但是对于具有嵌套对象的数据,浅拷贝只拷贝第一层对象,深层次的值仍然是复制引用地址。

  let a = {name: "mike",language: {first: "english",second: "chinese"}}let b = {}b.name = a.nameb.name = "jack"b.language = a.languageb.language.first = "japanese"console.log(a) // {"name":"mike", language : {first: "japanese", second: "chinese"}}

js实现浅拷贝,思想:遍历target的每个属性,将起属性名和值赋值给新变量。

如果你明白了赋值的含义,那么在代码的第四行,当此时的target[key]的值是对象的时候,通过赋值赋予新变量,本质上是复制引用数据类型在堆中的地址,就不难理解为什么浅拷贝对于是否是嵌套对象的有不同结果了。

  function shallowCopy(target) {let result = {}for (const key in target) {result[key] = target[key]}return result}

4、深拷贝

深拷贝是完完全全的拷贝,新旧变量之间不会相互影响。

对于参数是否是对象有不同的处理方法,如果是对象,对于对象的每个属性和值赋值然后递归处理; 否则直接返回。

  function clone(target) {if (typeof target === "object") {//判断是否是数组let result = Array.isArray(target) ? [] : {}for (const key in target) {result[key] = clone(target[key])}return result}else {return target}}

到此这篇关于js中的赋值 浅拷贝和深拷贝详细的文章就介绍到这了

 **************************************************************************************************************

补充——浅拷贝和深拷贝的更加完善的函数

  // 浅拷贝const shallowClone = target => {// 基本数据类型直接返回if (typeof target === 'object' && target !== null) {// 获取target 的构造体const constructor = target.constructor// 如果构造体为以下几种类型直接返回if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) {return target}// 判断是否是一个数组const cloneTarget = Array.isArray(target) ? [] : {}for (prop in target) {// 只拷贝其自身的属性if (target.hasOwnProperty(prop)) {cloneTarget[prop] = target[prop]}}return cloneTarget} else {return target}}
  // 深拷贝const completeDeepClone = (target, map = new WeakMap()) => {// 基本数据类型,直接返回if (typeof target !== 'object' || target === null) {return target}// 函数 正则 日期 ES6新对象,执行构造题,返回新的对象const constructor = target.constructorif (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) {return new constructor(target)}// map标记每一个出现过的属性,避免循环引用if (map.get(target)) {return map.get(target)}map.set(target, true)const cloneTarget = Array.isArray(target) ? [] : {}for (prop in target) {// 实现一个深拷贝函数通常需要递归地检查每个属性,如果属性值是对象,则递归调用自身进行拷贝;否则,直接复制该属性值。if (target.hasOwnProperty(prop)) {cloneTarget[prop] = completeDeepClone(target[prop], map)}}return cloneTarget}

补充——骚操作之JSON.parse(JSON.stringify(obj))

  let obj5 = {name: "mary",age: 17,grade: {maths: 60,arrGrade: [1, 2, 3],},arr: [1, 2, 3],fn: function add(str) {console.log(str)},undefinedData: undefined,RegExp: /^([0]{2}|0[1-9]|[1-9])\d*$/,date: new Date()}let obj6 = JSON.parse(JSON.stringify(obj5))obj6.age = 25obj6.grade.maths = 70console.log("obj5: ", obj5)console.log("obj6: ", obj6)

 

缺陷:

1、属性值为函数和undefined的属性会丢失

2、属性值为正则表达式的会变成{}

3、属性值为时间对象的会变成时间字符串

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

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

相关文章

三端全隔离485中继器光电隔离工业级 RS485集线器2口信号放大器 抗干扰防雷

485中继器光电隔离工业级 RS485集线器2口信号放大器 抗干扰防雷https://item.taobao.com/item.htm?ftt&id713033449656 哪里信号不好,中继器就接哪里 将有效的对信号进行隔离放大 信号隔离 电源隔离 双向传输 即插即用 增强抗干扰 延长通信距离 产品概…

防火墙详解(二)通过网页登录配置华为eNSP中USG6000V1防火墙

配置步骤 步骤一 打开eNSP,建立如下拓扑。防火墙使用:USG6000V1。 Cloud的作用是通过它可以连接本地的网卡,然后与我们的电脑进行通信。 由于防火墙USG6000V,不能直接开启,需要的导入包,所以需要在华为官网…

爬虫过程 | 蜘蛛程序爬取数据流程(初学者适用)

蜘蛛程序(也称网络爬虫,是搜索引擎的重要组成部分) 主要功能:遍历互联网,抓取网站信息并建立索引,便于用户在搜索引擎中检索到最新的网页内容工作原理:从初始网站页面的URL开始,发送…

【人工智能】看我如何用4个AI大模型,实现了堪比o1-preview的思维链。内含3个AI问答的数据比对结果!

在当今人工智能的快速发展中,如何高效地利用不同的AI模型来提升工作效率,成为了许多开发者和企业关注的焦点。本文将深入探讨如何通过4个GPT-4o模型与其他多模型的编排,构建一个强大的AI工作流,并与o1-preview的数据结果进行对比&…

怎么录屏?免费录屏软件推荐,电脑屏幕与摄像头内容录制与分享指南

在数字化办公和在线教育日益普及的今天,录屏软件成为了我们不可或缺的工具。无论是制作教学视频、游戏直播,还是远程会议记录,一个好的录屏软件都能让这些任务变得轻而易举。但面对市场上琳琅满目的录屏软件,我们该如何选择呢&…

国内短剧cps系统和短剧(播放)系统的区别,附各源码部署教程

国内短剧项目主要分为两大形式:一种是做短剧播放平台,让用户付费观看;另一种是做短剧的分销,就是将他人的平台短剧推广,可做平台可入驻,拿分成。 首先来说一下短剧播放平台(短剧系统&#xff0…

【推荐100个unity插件之26】Unity 地形Terrain的绘制和使用进阶内容 —— Terrain Tools和 Terrain Toolbox的使用

文章目录 前言一、Terrain Toolbox的使用安装Terrain Tools下载导入资产样本打开选择Terrain Toolbox创建地形切割地形创建不同分组的地形terrain group设置第一个pixel error是LOD精度,值越小精度越高,当然性能开销也就越大第二个base map distance是指…

【网络安全】TCP和UDP

一、TCP/UDP对比 1.共同点: 都是工作在TCP/IP体系结构的传输层的协议 工作主要都是把端口号往原始数据封装 在 TCP 协议中,原始数据指的是应用程序产生的需要通过网络进行传输的数据。这些数据可以是各种类型的信息,例如文本、图像、音频、…

200Kg大载重多旋翼无人机应用前景详解

大载重多旋翼无人机是一类具备高载重能力和长航时特点的无人机系统,它们融合了多旋翼无人机的灵活性与大载重无人机的实用性,广泛应用于多个领域。 1. 航拍与影视制作 在航拍与影视制作领域,200Kg大载重多旋翼无人机凭借其出色的稳定性和载重…

mysql时间戳格式化yyyy-mm-dd

格式化到 年月日 # 将时间换成列名就行;当前是秒级时间戳,如果是毫秒的 / 1000即可 # SELECT FROM_UNIXTIME(1602668106666.777888999 / 1000,%Y-%m-%d) AS a; # SELECT FROM_UNIXTIME(列名 / 1000,%Y-%m-%d) AS a; SELECT FROM_UNIXTIME(1602668106.666…

动手学深度学习(四)卷积神经网络-下

全连接层存在的问题:参数过大,计算成本过高。 一、网络中的网络(NiN) 1、NiN块 ①NiN块的结构 NiN串联多个由卷积层和“全连接”层构成的小网络来构建一个深层网络。这种由卷积层和“全连接”层构成的小网络就是NiN块。 &#…

【学习笔记】 AD24中元器件重叠系统不报错的解决方案(消除报错)

【学习笔记】 AD24中PCB设计元器件重叠后系统不报错的解决方案(如何主动屏蔽报错) 一、Component Clearance未开启使能的解决方案二、最小水平间距设置错误的解决方案三、未开启设计规则检查的解决方案四、设计规则检查中 “在线”和“批量”的含义五、为…

Matplotlib绘制热力图

热力图(Heatmap)是一种使用颜色来表示数值强度的数据可视化工具。它常用于以下场景: 热力图的适用场景 数据的相关性分析:在统计学中,热力图常用于展示变量之间的相关性,尤其是当数据量较大时,…

Vue(14)——组合式API①

setup 特点&#xff1a;执行实际比beforeCreate还要早&#xff0c;并且获取不到this <script> export default{setup(){console.log(setup函数);},beforeCreate(){console.log(beforeCreate函数);} } </script> 在setup函数中提供的数据和方法&#xff0c;想要在…

普通查询+聚合函数的使用(8个例子,数值和字符串的比较)

目录 回顾普通查询聚合函数的使用 表数据 例子1 例子2 例子3 ​​​​​​​例子4 例子5 例子6 例子7(数值和字符串的比较) 例子8 回顾普通查询聚合函数的使用 之前我们介绍过聚合函数 --mysql分组查询 -- 聚合函数(介绍,使用),group by使用,分组聚合统计(使用,havi…

【Unity杂谈】iOS 18中文字体显示问题的调查

一、问题现象 最近苹果iOS 18系统正式版推送&#xff0c;周围升级系统的同事越来越多&#xff0c;有些同事发现&#xff0c;iOS 18上很多游戏&#xff08;尤其是海外游戏&#xff09;的中文版&#xff0c;显示的字很奇怪&#xff0c;就像一些字被“吞掉了”&#xff0c;无法显示…

【ArcGIS微课1000例】0123:数据库中要素类批量转为shapefile

除了ArcGIS之外的其他GIS平台,想要打开ArcGIS数据库,可能无法直接打开,为了便于使用shp,建议直接将数据库中要素类批量转为shapefile。 文章目录 一、连接至数据库二、要素批量转shp一、连接至数据库 打开ArcMap,或者打开ArcCatalog,找到数据库连接,如下图: 数据库为个…

人工智能的前景与未来就业市场:机遇、挑战与社会影响

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐渗透到我们生活的方方面面&#xff0c;它不仅引领着技术革新的浪潮&#xff0c;更在无声中重塑着我们的就业市场和社会结构。站在这个时代的交汇点上&#xff0c;我们不禁要问&#xff1a;人工智能将…

Vue2学习笔记(02条件渲染 、监视数据的原理)

1、v-if和v-show的区别 2、Vue监视数据的原理

Ansible部署与应用基础

由于互联网的快速发展导致产品更新换代速度逐步增长&#xff0c;运维人员每天都要进行大量的维护操作&#xff0c;按照传统方式进行维护使得工作效率低下。这时部署自动化运维就 可以尽可能安全、高效的完成这些工作。 一、Ansible概述 1.什么是Ansible Ansible 是基于 Pytho…