JS核心知识点 - 赋值、浅拷贝、深拷贝。

一、理解基础数据类型和引用数据类型

  1. 基础数据类型

    • 字符串(String):表示文本数据,使用引号括起来。
    • 数字(Number):表示数值数据,包括整数和浮点数。
    • 布尔值(Boolean):表示逻辑值,即 true 或 false。
    • 空值(Null):表示一个空值或不存在的值。
    • 未定义(Undefined):表示一个未定义的值。
    • 符号(Symbol)(ES6新增):表示唯一的、不可改变的值。
  2. 引用数据类型

    • 对象(Object):表示复杂数据结构,可以包含多个键值对。
    • 数组(Array):一种特殊的对象,用于存储多个值。
    • 函数(Function):也是对象的一种,用于封装可执行的代码块。
    • 日期(Date):表示日期和时间。
    • 正则表达式(RegExp):用于匹配字符串的模式。
    • 其他引用数据类型:如 Map、Set 等(ES6新增)。

        基础数据类型存储在栈内存中,并且它们的值直接按值访问,因此可以直接操作实际的值(基础数据类型进行赋值操作时,会创建一个新的值,而不是共享同一块内存地址。)。而引用数据类型的值存储在堆内存中,栈内存中存储的是指向堆内存中实际数据的引用,因此对引用数据类型的操作实际上是对内存地址的操作,多个变量或对象可以共享同一个引用,导致共享内存地址。

二、赋值、浅拷贝、深拷贝的概念。

        赋值:赋值是指将一个变量的值或引用复制给另一个变量。在赋值操作中,如果原始数据是引用类型(如对象、数组),则赋值操作后两个变量将指向同一块内存地址,修改其中一个变量的值也会影响另一个变量。

        浅拷贝:浅拷贝是指创建一个新的对象或数组,然后将原始对象或数组中的元素复制到新对象或数组中。浅拷贝只复制对象或数组的第一层结构,如果对象或数组中包含引用类型的元素(如嵌套对象、数组),则这些引用类型的元素仍然是共享的,即新旧对象中的引用类型元素指向同一块内存地址。

        深拷贝:深拷贝是指创建一个全新的对象或数组,并且递归地复制原始对象或数组中的所有嵌套对象或数组,确保新对象与原始对象完全独立,互不影响。深拷贝会复制整个对象的结构,包括所有嵌套的对象和数组,每个元素都是独立的,不存在共享引用。

        总结: 赋值是简单的值或引用传递,在引用类型中会共享内存地址浅拷贝会复制第一层结构,但嵌套结构还是共享内存地址;而深拷贝则会复制所有层级的结构,确保完全独立。在编程中,根据需求选择适当的复制方式非常重要,以避免意外的数据改动和副作用。

三、赋值、浅拷贝、深拷贝的应用场景、实现方式

1、赋值

应用场景: 

处理基本数据类型时,直接赋值是最简单的方式。

处理引用数据类型的时候需要考虑是否要修改原数据、修改的话可以用赋值。

实现演示

代码
<template><div class="home"><h3>这是vue2测试页面</h3><p>num值:{{ num }}</p><p>obj:{{ obj }}</p><p><button @click="change">修改信息</button></p></div>
</template><script>export default {data() {return {num: '1',obj: { name: 'zs', age: 20 }}},created() {},methods: {change() {let newNum = this.num;newNum = 2;let newObj = this.objnewObj.age = '18'console.log('num的值为: '+ this.num + ' newNum的值为: ' + newNum);console.log('obj的值为: '+ this.obj + ' newObj的值为: ' + newObj);}},
}
</script>
<style>.home{margin: 0 auto;text-align: center;}
</style>
未点击修改按钮前

点击修改按钮后

结论

通过赋值、基础数据类型的数据赋值给一个新数据、新数据改变不影响旧数据(不共享内存空间)

通过赋值、引用数据类型的数据赋值给一个新数据、新数据改变影响旧数据(共享内存空间)

2、浅拷贝

应用场景: 

处理引用数据类型的时、希望修改新数据(新数据没有嵌套引用类型)时不影响原数据。

实现演示

代码
   实现浅拷贝的几种不同方式代码
// 方式一、使用ES6的展开运算符(...) 适用于对象和数组
// 浅拷贝对象
const originalObject = { name: 'Alice', age: 30 };
const shallowCopyObject = { ...originalObject };// 浅拷贝数组
const originalArray = [1, 2, 3];
const shallowCopyArray = [...originalArray];console.log(shallowCopyObject); // 输出: { name: 'Alice', age: 30 }
console.log(shallowCopyArray); // 输出: [1, 2, 3]// 方式二、使用Object.assign()方法 适用于对象
const originalObject = { name: 'Bob', age: 25 };
const shallowCopyObject = Object.assign({}, originalObject);console.log(shallowCopyObject); // 输出: { name: 'Bob', age: 25 }// 方式三、使用Array.slice()方法 适用于数组
const originalArray = [7, 8, 9];
const shallowCopyArray = originalArray.concat();console.log(shallowCopyArray); // 输出: [7, 8, 9]// 方式四、使用Array.concat()方法 适用于数组
const originalArray = [7, 8, 9];
const shallowCopyArray = originalArray.concat();console.log(shallowCopyArray); // 输出: [7, 8, 9]
实现浅拷贝效果代码
<template><div class="home"><h3>这是vue2测试页面</h3><p>num值:{{ num }}</p><p>obj:{{ obj }}</p><p><button @click="change">修改信息</button></p></div>
</template><script>export default {data() {return {num: '1',obj: { name: 'zs', age: 20, family: { son:'ls', daughter:'ww' }},arr: [1,2,3,4],}},created() {},methods: {change() {let newNum = this.num;newNum = 2;let newObj = {...this.obj}newObj.age = 18newObj.family.son = 'zl'console.log('num的值为: '+ this.num + ' newNum的值为: ' + newNum);console.log(this.obj, newObj);}},
}
</script>
<style>.home{margin: 0 auto;text-align: center;}
</style>
未点击修改按钮前

点击修改按钮后

结论

引用数据类型的数据浅拷贝给一个新数据

新数据基础数据类型数据的改变不影响旧数据(不共享内存空间)

新数据引用数据类型的改变影响旧数据(不共享内存空间)

3、深拷贝

应用场景: 

处理引用数据类型的时、希望修改新数据(新数据包含嵌套引用类型)时不影响原数据。

使用深拷贝时,需要考虑性能开销、循环引用、数据类型的处理、不可枚举属性的保留以及对象方法的处理等问题

实现演示

代码
   实现深拷贝的几种不同方式代码
// 方式一 使用 JSON.stringify() 和 JSON.parse() 适用于对象和数组的深拷贝。但请注意,它无法拷贝一些特殊类型,如函数、正则表达式等
const originalObject = { name: 'Alice', age: 30 };
const deepCopyObject = JSON.parse(JSON.stringify(originalObject));console.log(deepCopyObject); // 输出: { name: 'Alice', age: 30 }// 方式二、使用递归
function deepCopy(obj) {if (typeof obj !== 'object' || obj === null) {return obj;}let copy;if (Array.isArray(obj)) {copy = [];for (let i = 0; i < obj.length; i++) {copy[i] = deepCopy(obj[i]);}} else {copy = {};for (let key in obj) {if (obj.hasOwnProperty(key)) {copy[key] = deepCopy(obj[key]);}}}return copy;
}const originalObject = { name: 'Bob', age: 25 };
const deepCopyObject = deepCopy(originalObject);console.log(deepCopyObject); // 输出: { name: 'Bob', age: 25 }// 使用第三方库:如 Lodash 的 cloneDeep() 方法和 jQuery 的 extend() 方法
// 使用 Lodash 的 cloneDeep() 方法
const originalObject = { name: 'Alice', age: 30 };
const deepCopyObject = _.cloneDeep(originalObject);console.log(deepCopyObject); // 输出: { name: 'Alice', age: 30 }// 使用 jQuery 的 extend() 方法
const originalObject = { name: 'Bob', age: 25 };
const deepCopyObject = $.extend(true, {}, originalObject);console.log(deepCopyObject); // 输出: { name: 'Bob', age: 25 }
实现深拷贝效果代码
<template><div class="home"><h3>这是vue2测试页面</h3><p>num值:{{ num }}</p><p>obj:{{ obj }}</p><p><button @click="change">修改信息</button></p></div>
</template><script>export default {data() {return {num: '1',obj: { name: 'zs', age: 20, family: { son:'ls', daughter:'ww' }},arr: [1,2,3,4],}},created() {},methods: {change() {let newNum = this.num;newNum = 2;let newObj = JSON.parse(JSON.stringify(this.obj))newObj.age = 18newObj.family.son = 'zl'console.log('num的值为: '+ this.num + ' newNum的值为: ' + newNum);console.log(this.obj, newObj);}},
}
</script>
<style>.home{margin: 0 auto;text-align: center;}
</style>
未点击修改按钮前

点击修改按钮后

结论

引用数据类型的数据深拷贝给一个新数据

新数据改变不影响旧数据(不共享内存空间)

四、总结

1、赋值

处理基本数据类型时,直接赋值是最简单的方式(会生成一个新的内存空间、不会共享内存空间,即不会修改原数据)。

处理引用数据类型的时候需要考虑新数据修改是否能影响原数据、能影响的话可以用赋值(不会生成一个新的内存空间、会共享内存空间,会修改原数据)。

2、浅拷贝

处理引用数据类型的时、希望修改新数据时不能影响原数据(基础数据类型修改后原数据不会修改、引用数据类型修改后原数据会修改)。

3、深拷贝(慎用)

处理引用数据类型的时、希望修改新数据时不能影响原数据(基础数据类型修改后和引用数据类型修改后原数据都不会修改)。

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

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

相关文章

vulhub中Apache Shiro 认证绕过漏洞复现(CVE-2010-3863)

Apache Shiro是一款开源安全框架&#xff0c;提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用&#xff0c;同时也能提供健壮的安全性。 在Apache Shiro 1.1.0以前的版本中&#xff0c;shiro 进行权限验证前未对url 做标准化处理&#xff0c;攻击者可以构造/、//、…

[ Linux ] vim的使用(附:命令模式的常见命令列表)

1.下载安装 这里是在通过yum进行下载安装 yum install -y vim 2.了解 vim是一款编辑器&#xff0c;它具有多模式的特点 主要有&#xff1a;插入模式&#xff0c;命令模式&#xff0c;底行模式 3.使用 打开 vim 文件名 命令模式的常见命令列表 插入模式 按「 i 」切换…

A Survey on Multimodal Large Language Models

目录 1. Introduction2. 概述方法多模态指令调优 3.1.1 简介3.1.2 预备知识3.1.3 模态对齐3.1.4 数据3.1.5 模态桥接3.1.6 评估 3.2.多模态情境学习3.3.多模态思维链3.3.1 模态桥接3.3.2 学习范式3.3.3 链配置3.3.4 生成模式3.4.LLMs辅助视觉推理3.4.1 简介3.4.2 训练范式3.4.3…

医疗隔离电源系统在医院配电系统应用分析

【摘要】根据医疗场所分类说明医院尤其是 2 类 医疗场所的接地方案&#xff0c;分析医疗场所自动切断电源措 施&#xff0c;提出校验医疗 IT 系统配出回路长度&#xff1b;说明 RCD、RCM、IMD、IFLS 等的用途和范围&#xff1b;就应急医 院 2 类场所的配电方案进行探讨。 【关…

B005-springcloud alibaba 服务网关 Gateway

目录 网关简介Gateway简介Gateway快速入门基础版增强版简写版 Gateway概念及执行流程基本概念执行流程 断言Gateway内置路由断言内置路由断言工厂的使用 自定义路由断言工厂 过滤器过滤器简介局部过滤器内置局部过滤器自定义局部过滤器 全局过滤器内置全局过滤器自定义全局过滤…

【机器学习】详细解析Sklearn中的StandardScaler---原理、应用、源码与注意事项

【机器学习】详细解析Sklearn中的StandardScaler—原理、应用、源码与注意事项 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x…

用python写网络爬虫:3.urllib库进一步的使用方法

文章目录 异常处理URLErrorHTTPError设置超时时间 链接的解析、构造、合并urlparse方法urlsplit方法urljoin方法urlencode方法parse_qs方法quote方法 Robots 协议Robots 协议的结构解析协议 参考书籍 在上一篇文章&#xff1a;用python写网络爬虫&#xff1a;2.urllib库的基本用…

STM32中freertos任务不能调度的原因解决

本文是项目中的定位问题&#xff0c;如果定位到同样问题&#xff0c;可以按下面方法解决。 问题定位 这行assert代码主要判断系统中最大中断优先级数量是否等于内核中断优先级&#xff0c;实际意思就是要求内核中断优先级为系统最低优先级&#xff08;freertos中0为最高优先级…

2024/3/17 TCP的进程和线程通信,模拟面试总结

#include<myhead.h> #define SER_PORT 8888//服务器端口号 #define SER_IP "192.168.65.130"//服务器IP //定义向线程体提供参数的结构体 struct BufInfo {int newfd;struct sockaddr_in cin; }; //定义线程体函数 void *deal_cli_msg(void *arg) {//接受传过来…

初次文件包含漏洞

1.文件包含漏洞介绍 1.1.文件包含漏洞解释   文件包含漏洞就是使用函数去包含任意文件的时候&#xff0c;当包含的文件来源过滤不严谨的时候&#xff0c;当存在包含恶意文件后&#xff0c;就可以通过这个恶意的文件来达到相应的目的。 1.2.文件包含漏洞原理    其实原理就…

四、MySQL

MySQL MySQL1.初识网站2.安装MySQL2.1 下载&#xff08;最重要的一点是路径中不能有中文&#xff0c;哪怕是同级目录也不行&#xff09;2.2安装补丁2.3安装2.4创建配置文件2.5初始化 3.启动MySQL4.连接测试4.1 设置密码4.2 查看已有的文件夹&#xff08;数据库&#xff09;4.3 …

Linux怎么查看当前进程?怎么执行退出?怎么查看当前路径?

在Linux系统中&#xff0c;查看当前进程、执行退出和查看当前路径都可以通过命令行来完成。下面是具体的命令和它们的用法&#xff1a; 1. **查看当前进程**&#xff1a; 使用ps命令可以查看当前运行的进程。ps代表“process status”&#xff0c;它可以显示当前用户的进程…

计算机网络——物理层(信道复用技术)

计算机网络——物理层&#xff08;信道复用技术&#xff09; 信道复用技术频分多址与时分多址 频分复用 FDM (Frequency Division Multiplexing)时分复用 TDM (Time Division Multiplexing)统计时分复用 STDM (Statistic TDM)波分复用码分复用 我们今天接着来看信道复用技术&am…

用Excel就可以实现的生产绩效考核评定

从事生产管理数十载&#xff0c;在进行员工日常生产效率和综合考核的管理方面&#xff0c;积累了一些经验和注意事项。今天来和大家分享一下如何用Excel来搞定它吧&#xff01; 首先&#xff0c;Excel是一个强大的工具&#xff0c;可以帮助我们收集、分析和展示员工的生产数据…

掌握Go语言:Go语言中的字典魔法,高效数据检索与应用实例解析(18)

在Go语言中&#xff0c;字典通常指的是map类型&#xff0c;它是一种用于存储键值对的数据结构。字典在Go中非常常见&#xff0c;是一种高效的数据结构&#xff0c;用于快速查找和检索数据。 字典的详细使用方法 创建字典 可以使用make函数来创建字典&#xff0c;并指定键值对…

生成器建造者模式(Builder)——创建型模式

生成器/建造者模式——创建型模式 什么是生成器模式&#xff1f; 生成器模式是一种创建型设计模式&#xff0c; 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 提炼两个关键点&#xff1a;Ⅰ.分步骤创建复杂对象。Ⅱ.相同创建代码…

llm综述

1、语言模型进程 1.1、语言模型概述 语言模型从统计语言模型&#xff08;SLM&#xff09;逐步发展为神经语言模型&#xff08;NLM&#xff09;&#xff1b;近年&#xff0c;通过在大规模语料库上对 Transformer 模型进行预训练&#xff0c;预训练语言模型(Pre-training Langu…

Windows程序员用MAC:安装win双系统、wintogo和删除

初级代码游戏的专栏介绍与文章目录-CSDN博客 这是本人用mac的操作记录&#xff0c;型号为MBP2019(intel CPU)。 大部分操作是基于较早的MAC系统&#xff08;大约是2021年年底到2022年年初&#xff09;&#xff0c;提及的“新版”是2023年年初。这篇文章的目的不是让你照着做就能…

面试经典-29- 插入区间

题目 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表。 在列表中插入一个新的区间&#xff0c;你需要确保列表中的区间仍然有序且不重叠&#xff08;如果有必要的话&#xff0c;可以合并区间&#xff09;。 示例 1&#xff1a; 输入&#xff1a;intervals …

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:EffectComponent)

特效合并容器组件&#xff0c;用于子节点特效绘制的合并&#xff0c;实现特效的绘制性能优化。 说明&#xff1a; 该组件从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 该组件为系统接口。 目前该组件仅支持子组件背景…