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

理解 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))
  • 优点:简单易用。

  • 缺点

    • 不能处理函数、undefinedSymbol 等特殊类型。

    • 不能处理循环引用(即对象内部属性引用自身)。

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&#xf…...

考研机试常见基本题型

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面纱

前言&#xff1a; 继上一篇Android AudioFlinger&#xff08;三&#xff09;—— AndroidAudio Flinger 之设备管理我们知道PlaybackThread继承自Re’fBase&#xff0c; 在被第一次引用的时候就会调用onFirstRef&#xff0c;实现如下&#xff1a; void AudioFlinger::Playbac…...

C语言基础系列【20】内存管理

博主介绍&#xff1a;程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章&#xff0c;首发gzh&#xff0c;见文末&#x1f447;&#x1f…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

图解JavaScript原型:原型链及其分析 | JavaScript图解

​​ 忽略该图的细节&#xff08;如内存地址值没有用二进制&#xff09; 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么&#xff1a;保存在堆中一块区域&#xff0c;同时在栈中有一块区域保存其在堆中的地址&#xff08;也就是我们通常说的该变量指向谁&…...