理解 JavaScript 中的浅拷贝与深拷贝
在 JavaScript 开发中,我们经常需要复制对象或数组。然而,复制的方式不同,可能会导致不同的结果。本文将详细介绍 浅拷贝 和 深拷贝 的概念、区别以及实现方式,帮助你更好地理解和使用它们。
1. 什么是浅拷贝?
定义
浅拷贝是指只复制对象的第一层属性。如果对象的属性是引用类型(如对象、数组等),则复制的是引用地址,而不是实际的值。
特点
-
新对象和原对象共享内部的引用类型字段。
-
修改原对象的引用类型字段,浅拷贝的对象也会受到影响。

实现方式
在 JavaScript 中,浅拷贝可以通过以下方式实现:
-
使用
Object.assign() -
使用扩展运算符
{...obj} -
使用数组的
slice()或concat()方法(针对数组)
示例
const original = { a: 1, b: { c: 2 } };
const shallowCopied = { ...original }; // 使用扩展运算符实现浅拷贝// 修改原对象的引用类型字段
original.b.c = 100;console.log(original); // { a: 1, b: { c: 100 } }
console.log(shallowCopied); // { a: 1, b: { c: 100 } },浅拷贝对象也被修改
2. 什么是深拷贝?
定义
深拷贝是指递归地复制对象及其内部的所有引用类型字段,生成一个完全独立的新对象。
特点
-
新对象和原对象完全独立。
-
修改原对象的引用类型字段,深拷贝的对象不会受到影响。

实现方式
深拷贝的实现方式有多种,以下是常见的几种方法:
方法 1:使用 JSON.parse(JSON.stringify(obj))
-
优点:简单易用。
-
缺点:
-
不能处理函数、
undefined、Symbol等特殊类型。 -
不能处理循环引用(即对象内部属性引用自身)。
-
const original = { a: 1, b: { c: 2 } };
const deepCopied = JSON.parse(JSON.stringify(original));// 修改原对象的引用类型字段
original.b.c = 100;console.log(original); // { a: 1, b: { c: 100 } }
console.log(deepCopied); // { a: 1, b: { c: 2 } },深拷贝对象不受影响
方法 2:递归实现深拷贝
-
优点:可以处理更多数据类型(如函数、
undefined等)。 -
缺点:需要手动处理循环引用。
function deepClone(obj, cache = new WeakMap()) {// 如果是基本类型或 null,直接返回if (obj === null || typeof obj !== 'object') {return obj;}// 如果对象已经被拷贝过,直接返回缓存的结果(避免循环引用)if (cache.has(obj)) {return cache.get(obj);}// 处理数组if (Array.isArray(obj)) {const clonedArr = [];cache.set(obj, clonedArr);obj.forEach((item) => {clonedArr.push(deepClone(item, cache));});return clonedArr;}// 处理普通对象const clonedObj = {};cache.set(obj, clonedObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {clonedObj[key] = deepClone(obj[key], cache);}}return clonedObj;
}// 测试
const original = { a: 1, b: { c: 2 }, d: [3, 4] };
const deepCopied = deepClone(original);// 修改原对象
original.b.c = 100;
original.d.push(5);console.log(original); // { a: 1, b: { c: 100 }, d: [3, 4, 5] }
console.log(deepCopied); // { a: 1, b: { c: 2 }, d: [3, 4] },深拷贝对象不受影响
方法 3:使用第三方库(如 Lodash)
-
优点:功能强大,支持各种数据类型和循环引用。
-
缺点:需要引入额外的库。
// 安装 lodash:npm install lodash
const _ = require('lodash');const original = { a: 1, b: { c: 2 } };
const deepCopied = _.cloneDeep(original);// 修改原对象
original.b.c = 100;console.log(original); // { a: 1, b: { c: 100 } }
console.log(deepCopied); // { a: 1, b: { c: 2 } },深拷贝对象不受影响
3. 浅拷贝 vs 深拷贝
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制层级 | 只复制第一层属性 | 递归复制所有层级属性 |
| 引用类型字段 | 共享引用地址 | 完全独立 |
| 修改原对象影响 | 影响浅拷贝对象 | 不影响深拷贝对象 |
| 实现方式 | Object.assign()、扩展运算符等 | JSON.parse(JSON.stringify())、递归、Lodash 等 |
4. 如何选择拷贝方式?
-
浅拷贝:适用于对象结构简单或不需要独立内部引用的情况。
-
深拷贝:适用于对象结构复杂或需要完全独立副本的情况。
5. 总结
在 JavaScript 中,浅拷贝和深拷贝是两种常见的对象复制方式。浅拷贝只复制对象的第一层属性,而深拷贝会递归复制对象及其所有内部引用类型字段。根据实际需求选择合适的拷贝方式,可以避免不必要的 bug 和数据污染。
希望本文能帮助你更好地理解浅拷贝和深拷贝的概念与实现方式。如果你有更多问题,欢迎在评论区留言讨论!
相关文章:
理解 JavaScript 中的浅拷贝与深拷贝
在 JavaScript 开发中,我们经常需要复制对象或数组。然而,复制的方式不同,可能会导致不同的结果。本文将详细介绍 浅拷贝 和 深拷贝 的概念、区别以及实现方式,帮助你更好地理解和使用它们。 1. 什么是浅拷贝? 定义 …...
【Java开发指南 | 第三十五篇】Maven + Tomcat Web应用程序搭建
读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 前言Maven Tomcat Web应用程序搭建1、使用Maven构建新项目2、单击项目,连续按两次shift键,输入"添加",选择"添加框架支持"3、选择Java Web程序4、点击&…...
从0到1入门Linux
一、常用命令 ls 列出目录内容 cd切换目录mkdir创建新目录rm删除文件或目录cp复制文件或目录mv移动或重命名文件和目录cat查看文件内容grep在文件中查找指定字符串ps查看当前进程状态top查看内存kill终止进程df -h查看磁盘空间存储情况iotop -o直接查看比较高的磁盘读写程序up…...
golang 从零单排 (一) 安装环境
1.下载安装 打开网址The Go Programming Language 直接点击下载go1.24.1.windows-amd64.msi 下载完成 直接双击下一步 下一步 安装完成 环境变量自动设置不必配置 2.验证 win r 输入cmd 打开命令行 输入go version...
如何下载和使用Git:初学者指南
🌟 如何下载和使用Git:初学者指南 在当今的软件开发中,Git已经成为不可或缺的版本控制系统。无论你是独立开发者还是团队成员,掌握Git的基本操作都能帮助你更高效地管理代码。今天,我将详细介绍如何下载和使用Git&…...
SQL_语法
1 数据库 1.1 新增 create database [if not exists] 数据库名; 1.2 删除 drop database [if exists] 数据库名; 1.3 查询 (1) 查看所有数据库 show databases; (2) 查看当前数据库下的所有表 show tables; 2 数据表 2.1 新增 (1) 创建表 create table [if not exists…...
基于Python实现的智能旅游推荐系统(Django)
基于Python实现的智能旅游推荐系统(Django) 开发语言:Python 数据库:MySQL所用到的知识:Django框架工具:pycharm、Navicat 系统功能实现 总体设计 系统实现 系统首页模块 统首页页面主要包括首页,旅游资讯,景点信息…...
安孚科技携手政府产业基金、高能时代发力固态电池,开辟南孚电池发展新赛道
安孚科技出手,发力固态电池。 3月7日晚间,安孚科技(603031.SH)发布公告称,公司控股子公司南孚电池拟与南平市绿色产业投资基金有限公司(下称“南平绿色产业基金”)、高能时代(广东横…...
p5.js:模拟 n个彩色小球在一个3D大球体内部弹跳
向 豆包 提问:编写一个 p5.js 脚本,模拟 42 个彩色小球在一个3D大球体内部弹跳。每个小球都应留下一条逐渐消失的轨迹。大球体应缓慢旋转,并显示透明的轮廓线。请确保实现适当的碰撞检测,使小球保持在球体内部。 cd p5-demo copy…...
Kali WebDAV 客户端工具——Cadaver 与 Davtest
1. 工具简介 在 WebDAV 服务器管理和安全测试过程中,Cadaver 和 Davtest 是两款常用的命令行工具。 Cadaver 是一个 Unix/Linux 命令行 WebDAV 客户端,主要用于远程文件管理,支持文件上传、下载、移动、复制、删除等操作。Davtest 则是一款…...
MySQL复习笔记
MySQL复习笔记 1.MySQL 1.1什么是数据库 数据库(DB, DataBase) 概念:数据仓库,软件,安装在操作系统(window、linux、mac…)之上 作用:存储数据,管理数据 1.2 数据库分类 关系型数据库&#…...
六十天前端强化训练之第十四天之深入理解JavaScript异步编程
欢迎来到编程星辰海的博客讲解 目录 一、异步编程的本质与必要性 1.1 单线程的JavaScript运行时 1.2 阻塞与非阻塞的微观区别 1.3 异步操作的性能代价 二、事件循环机制深度解析 2.1 浏览器环境的事件循环架构 核心组件详解: 2.2 执行顺序实战分析 2.3 Nod…...
集合论--形式化语言里的汇编码
如果一阶逻辑是数学这门形式化语言里的机器码,那么集合论就是数学这门形式化语言里的汇编码。 基本思想:从集合出发构建所有其它。 构建自然数构建整数构建有理数构建实数构建有序对、笛卡尔积、关系、函数、序列等构建确定有限自动机(DFA) 全景图 常…...
2025最新群智能优化算法:山羊优化算法(Goat Optimization Algorithm, GOA)求解23个经典函数测试集,MATLAB
一、山羊优化算法 山羊优化算法(Goat Optimization Algorithm, GOA)是2025年提出的一种新型生物启发式元启发式算法,灵感来源于山羊在恶劣和资源有限环境中的适应性行为。该算法旨在通过模拟山羊的觅食策略、移动模式和躲避寄生虫的能力&…...
MySQL数据实时同步至Elasticsearch的高效方案:Java实现+源码解析,一文搞定!
引言:为什么需要实时同步? MySQL擅长事务处理,而Elasticsearch(ES)则专注于搜索与分析。将MySQL数据实时同步到ES,可以充分发挥两者的优势,例如: 构建高性能搜索服务 实时数据分析…...
Spring-事务
Spring 事务 事务的基本概念 🔹 什么是事务? 事务是一组数据库操作,它们作为一个整体,要么全部成功,要么全部回滚。 常见的事务场景: 银行转账(扣款和存款必须同时成功) 订单系统…...
Git系列之git tag和ReleaseMilestone
以下是关于 Git Tag、Release 和 Milestone 的深度融合内容,并补充了关于 Git Tag 的所有命令、详细解释和指令实例,条理清晰,结合实际使用场景和案例。 1. Git Tag 1.1 定义 • Tag 是 Git 中用于标记特定提交(commit…...
考研机试常见基本题型
1、求100以内的素数 sqrt()函数在cmath头文件中。 #include <iostream> #include <cmath> using namespace std;int main() {int count 0; // 用于统计素数的个数// 遍历 100 到 200 之间的每一个数for (int num 100; num < 200; num) {bool isPrime true…...
Android AudioFlinger(四)—— 揭开PlaybackThread面纱
前言: 继上一篇Android AudioFlinger(三)—— AndroidAudio Flinger 之设备管理我们知道PlaybackThread继承自Re’fBase, 在被第一次引用的时候就会调用onFirstRef,实现如下: void AudioFlinger::Playbac…...
C语言基础系列【20】内存管理
博主介绍:程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章,首发gzh,见文末👇…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
