前端JavaScript深拷贝与浅拷贝

news2024/12/28 18:58:13

 🎬 岸边的风:个人主页

 🔥 个人专栏 :《 VUE 》 《 javaScript 》

⛺️ 生活的理想,就是为了理想的生活 !

在这里插入图片描述

目录

引言

1. 深拷贝的实现

1.1 基本类型和特殊类型的处理

1.2 处理循环引用

1.3 性能优化

1.4 完整的深拷贝实现示例

2. 浅拷贝的实现

2.1 Object.assign()

2.2 展开语法(Spread Syntax)

2.3 数组浅拷贝

3. 深拷贝与浅拷贝的应用场景

4. 注意事项

结论


引言

在JavaScript中,对象的拷贝是一项常见的操作。浅拷贝和深拷贝是两种常用的拷贝方式。浅拷贝只复制对象的引用,而深拷贝创建了一个全新的对象,包含与原始对象相同的值和结构。深拷贝和浅拷贝各有适用的场景和注意事项。本文将详细介绍如何实现一个完整而优雅的深拷贝函数,处理循环引用和特殊类型,优化性能,并探讨深拷贝和浅拷贝的应用场景、注意事项和相关属性。

1. 深拷贝的实现

实现一个完整而优雅的深拷贝函数需要考虑以下几个方面:

1.1 基本类型和特殊类型的处理

在实现深拷贝函数时,首先需要处理基本类型(如字符串、数字、布尔值等)和特殊类型(如函数、正则表达式和日期对象等)。对于基本类型,直接返回其值即可。对于特殊类型,可以选择直接引用原始对象,而不进行复制。

function deepClone(obj) {
  // 处理基本类型
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  // 处理特殊类型
  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }

  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }

  if (obj instanceof Function) {
    return obj;
  }

  // 处理普通对象和数组
  const clone = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key]);
    }
  }

  return clone;
}

在上述代码中,我们使用 typeof 操作符判断基本类型,根据对象的类型选择适当的处理方式。对于函数、正则表达式和日期对象,我们使用相应的构造函数创建新的实例。

1.2 处理循环引用

循环引用是指对象属性之间存在相互引用的情况,导致递归复制陷入无限循环。为了处理循环引用,我们可以使用一个额外的数据结构(如 Map 或 WeakMap)来存储已经复制的对象,以便在遇到循环引用时进行判断和处理。

下面是一个修改后的 deepClone 函数,解决了循环引用问题:

function deepClone(obj, map = new Map()) {
  if (typeof obj !== 'object' || obj

 === null) {
    return obj;
  }

  if (map.has(obj)) {
    return map.get(obj);
  }

  const clone = Array.isArray(obj) ? [] : {};

  map.set(obj, clone);

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], map);
    }
  }

  return clone;
}

在上述代码中,我们使用 Map 数据结构来存储已经复制的对象。在每次递归调用时,我们首先检查 map 中是否存在当前对象的引用,如果存在则直接返回对应的副本。这样,我们可以避免陷入无限循环。

1.3 性能优化

深拷贝是一项相对耗费性能的操作,特别是在处理大型对象或嵌套层次很深的对象时。为了提高性能,可以考虑以下几个优化策略:

  • 循环拷贝:使用循环代替递归,减少函数调用的开销。这可以通过迭代对象的属性并复制它们来实现。
  • 使用 JSON 序列化与反序列化JSON.stringify() 方法可以将对象序列化为字符串,JSON.parse() 方法可以将字符串解析为对象。使用这两个方法可以快速实现深拷贝,但它的适用范围受限,无法处理特殊类型(如函数和正则表达式)和循环引用。
  • 使用库函数:许多优秀的 JavaScript 库(如 Lodash、Underscore)提供了高性能的深拷贝函数。这些库经过充分测试和优化,可以满足大多数深拷贝需求。

1.4 完整的深拷贝实现示例

下面是一个完整的深拷贝函数的实现,综合考虑了上述的处理方法:

// 也可以用WeakMap优化
function deepClone(obj, hash = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  if (hash.has(obj)) {
    return hash.get(obj);
  }

  const clone = Array.isArray(obj) ? [] : {};

  hash.set(obj, clone);

  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }

  if (obj instanceof RegExp) {
    const flags = obj.flags;
    const pattern = obj.source;
    return new RegExp(pattern, flags);
  }

  if (typeof obj === 'function') {
    return cloneFunction(obj);
  }

  const keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];

  for (const key of keys) {
    clone[key] = deepClone(obj[key], hash);
  }

  return clone;
}

function cloneFunction(func) {
  const body = func.toString();
  const parameters = body.match(/\((.*?)\)/)[1];
  const functionBody = body.substring(body.indexOf('{') + 1, body.lastIndexOf('}'));
  return new Function(parameters, functionBody);
}

2. 浅拷贝的实现

与深拷贝不同,浅拷贝只复制对象的引用,而不创建对象的副本。下面是几种常见的浅拷贝方法:

2.1 Object.assign()

Object.assign() 方法用于将所有可枚举属性从一个或多个源对象复制到目标对象,并返回目标对象。它只会复制源对象的属性的引用,而不是属性的值。

const sourceObj = { name:

 'John', age: 25 };
const targetObj = Object.assign({}, sourceObj);

console.log(targetObj); // 输出:{ name: 'John', age: 25 }

在上述代码中,我们使用 Object.assign() 方法将源对象的属性复制到目标对象中。targetObj 是 sourceObj 的浅拷贝副本。

2.2 展开语法(Spread Syntax)

展开语法(Spread Syntax)可以用于将一个对象的所有属性展开到另一个对象中。

const sourceObj = { name: 'John', age: 25 };
const targetObj = { ...sourceObj };

console.log(targetObj); // 输出:{ name: 'John', age: 25 }

在上述代码中,我们使用展开语法将源对象的所有属性展开到目标对象中。targetObj 是 sourceObj 的浅拷贝副本。

2.3 数组浅拷贝

对于数组的浅拷贝,可以使用 slice() 或展开语法。

const sourceArray = [1, 2, 3];
const targetArray1 = sourceArray.slice();
const targetArray2 = [...sourceArray];

console.log(targetArray1); // 输出:[1, 2, 3]
console.log(targetArray2); // 输出:[1, 2, 3]

在上述代码中,我们使用 slice() 方法和展开语法将源数组的元素复制到目标数组中。targetArray1 和 targetArray2 都是 sourceArray 的浅拷贝副本。

3. 深拷贝与浅拷贝的应用场景

深拷贝和浅拷贝各有适用的场景:

  • 深拷贝的应用场景

    • 当需要创建一个对象的完全独立副本时,以防止对原始对象的修改。
    • 在对象状态管理中,需要创建对象的副本以记录历史状态、实现撤销和重做等操作。
    • 在数据变换和处理过程中,创建对象的副本以避免对原始数据的修改。
  • 浅拷贝的应用场景

    • 当只需要复制对象的引用,而不需要创建对象的副本时。
    • 在一些简单的数据处理场景中,浅拷贝可以更高效地完成任务。

4. 注意事项

在使用深拷贝和浅拷贝时,需要注意以下几个问题:

  • 循环引用:深拷贝和浅拷贝都需要注意循环引用的问题。循环引用是指对象之间相互引用,导致无限循环。在处理循环引用时,深拷贝需要使用额外的数据结构(如 Map 或 WeakMap)进行记录和判断,而浅拷贝则无法解决循环引用的问题。
  • 特殊类型的处理:在实现深拷贝和浅拷贝时,需要注意特殊类型的处理。特殊类型包括函数、正则表达式等。对于特殊类型,深拷贝可以选择直接引用原始对象,而浅拷贝只会复制引用。
  • 性能开销:深拷贝是一项相对耗费性能的操作,特别是在处理大型对象或嵌套层次很深的对象时。在实际应用中,需要根据场景权衡性能和需求。

结论

深拷贝和浅拷贝是JavaScript中常用的拷贝方式,每种方式都有其适用的场景和注意事项。通过实现一个完整而优雅的深拷贝函数,我们可以轻松地创建对象的独立副本,并处理循环引用和特殊类型。浅拷贝则提供了一种快速复制对象的方式,适用于简单的数据处理场景。根据实际需求和性能要求,选择适合的拷贝方式,可以更好地满足业务需求。

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

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

相关文章

MES系统成为工业4.0首选,制造业真正数字化车间你看过吗?

在日益激烈的市场竞争中,MES管理系统已经成为企业提升生产效率、降低成本、提高竞争力的关键。通过MES管理系统实现数据集成和分析,能够对产品制造过程的各个环节进行可视化控制,从设计、制造、质量、物流等环节全面掌控信息,实现…

螺旋折线(找规律 + 准确取点优化分析 + 普通思路)【包含详细的思考过程】

螺旋折线 文章目录 螺旋折线前言题目描述题目分析优化思路知识点补充【曼哈顿距离】代码未优化思路【笨方法】 前言 在写完题目查看题解的时候,被acwing大佬的思路所震撼,所以按照自己的理解将 大佬的思路复刻一遍展现给大家,同时丰富了内容…

彩虹医疗器械彩超、内窥镜维修技能学习

近几年随着医疗行业的快速发展,医疗器械的需求量不断增加,同时对医疗器械的维修和保养需求也在不断增长随着医疗技术的不断进步,新型、复杂的医疗器械不断涌现,这对维修技术提出了更高的要求。加强技术研发是必经之路,…

Element Plus中Cascader 级联选择器(选择任意一级选项 - 更改下拉框选中方式)

组件原始选中&#xff1a;选择文字前面的单选按钮 现在更改为&#xff1a;隐藏单选按钮&#xff0c;点击文字进行选中 ① 给弹出内容的自定义类名(popper-class)&#xff1a; <el-cascader v-model"areaValue":options"areaOptions" :props"areaP…

算法刷题 week2

目录 week21. 二维数组中的查找题目题解(单调性扫描) O(nm) 2.替换空格题目题解(线性扫描) O(n)(双指针扫描) O(n) 3.从尾到头打印链表题目题解(遍历链表) O(n) week2 1. 二维数组中的查找 题目 题解 (单调性扫描) O(nm) 核心在于发现每个子矩阵右上角的数的性质&#xff1…

MySQL数据库技术笔记(1)

MySQL是一种关系数据库管理系统. 按照数据结构来组织、存储和管理数据的仓库. 数据库的发展&#xff1a; 1.层次模型存储&#xff1a;归为大类&#xff0c;分小类&#xff0c;也称树形结构 2.网状模型 3.关系模型&#xff1a;1对1的关系&#xff0c;1对多的关系&#xff0…

04目标检测-Two-stage的目标检测算法

目录 一、 深度学习目标检测算法介绍 二、 基于Two-stage的目标检测算法 三、Two-stage基本流程 四、Two-stage常见算法 五、Two-stage核心组件 1、Two-stage的两个核心组件 2、主干CNN网络设计原则 3、RPN网络 3.1 Faster R-CNN 网络结构 3.2 RPN&#xff08;Region…

安装rsa依赖库出现ERROR: No matching distribution found for rsa

通过安装离线包的方式安装python-rsa依赖包&#xff0c;出现错误 执行命令&#xff08;require 文件夹中是rsa-4.9.tar.gz文件&#xff0c;加粗&#xff0c;后面会用到&#xff09;pip install --no-index --find-link./require -r ./requirements.txt&#xff0c;出现以下错误…

Linux(CentOS)安装msf

目录 一、安装MSF 1.1 在线安装 1.2 离线安装 二、安装Postgresql数据库 一、安装MSF 1.1 在线安装 需要挂梯子&#xff01;挂完梯子需要reboot重启&#xff0c;多试几次就可以&#xff0c;国内网络我试了很久都不行。没条件没梯子的看1.2离线安装 cd /opt curl https://ra…

java springboot 如何实现小程序支付

今天给大家分享java小程序支付 首先我们学习任何东西要先看官网 下面是支付业务流程 我们具体用代码去实现上面的业务流程 功能截图 代码截图 pay(){//调用后台生成订单var orderNumber "20210101123456";var amount 0.01;WxPay.wxpay(app, amount, orderNumber…

Vue中的图像压缩与图片优化

Vue中的图像压缩与图片优化 在现代Web应用程序中&#xff0c;图像占据了大量的带宽和存储空间。因此&#xff0c;图像压缩和图片优化成为了开发者们不可或缺的任务之一。Vue.js作为一种流行的前端框架&#xff0c;提供了丰富的工具和生态系统&#xff0c;使图像处理变得更加简…

常用的管理方法论分享

在多年的软件研发团队管理过程中&#xff0c;我积累了一些方法&#xff0c;跟大家分享。 软件研发团队非常注重成本和效率&#xff0c;大多数管理者是从一线开发者升上去的。往往非常善于解决技术问题&#xff0c;但不知道如何管理下属&#xff0c;如何对待上级&#xff0c;如…

uniapp项目-HBuilderx打包问题

在项目中&#xff0c;有时候会有需求说要加一个文件前缀之类的&#xff0c; 比如&#xff1a;有些h5做映射时需要加一个项目名&#xff0c;那我们打包的时候就要在喷织文件做设置。 在manifest.json文件,把运行的基础路径改掉你所需要的就行了&#xff0c;默认d的是./

go开发之个人微信的二次开发

简要描述&#xff1a; 设置群公告 请求URL&#xff1a; http://域名地址/setChatRoomAnnouncement 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必…

短视频seo矩阵系统源码开发搭建--代用户发布视频能力

短视频SEO矩阵系统源码开发搭建的代用户发布视频能力&#xff0c;主要是指在系统平台上&#xff0c;允许用户将其创作的内容发布到指定的账号或平台&#xff0c;并设置好相关的标题、话题、锚点等信息。 一、搭建步骤及注意事项 确定使用场景。根据业务需求&#xff0c;确定该…

精品基于NET实现的课堂学分管理系统

《[含文档PPT源码等]精品基于NET实现的课堂学分管理系统》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等 软件开发环境及开发工具&#xff1a; 开发软件&#xff1a;VS 2017 &#xff08;版本2017以上即可&#xff0c;不能低于2017&#xff09; 数…

[qt]vs2022+qt5.13.2代码报错QChartView不明确

报错类似下面&#xff1a; 鼠标指上去错误代码显示QChartView不明确,解决方法 在xxx.ui对应的头文件包含”ui_xxx.h“的前方添加如下代码&#xff1a; #include <qchart.h> QT_CHARTS_USE_NAMESPACE

人力资源服务升级正当时,法大大助力佩信集团加速数字化

人力资源服务业是现代服务业的一个重要门类&#xff0c;在促进就业创业、提供人才服务方面发挥重要作用。同时面对产业转型升级、平台经济快速发展、企业用工成本提高等新形势&#xff0c;发展人力资源服务业对于促进社会化就业、更好发挥我国人力资源优势、服务经济社会发展具…

制定有效的开发规范:提升团队协作和代码质量的关键策略

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 在现代软件开发中…

python基础复习-基本语法元素

目录 基础语法元素列表元组字典集合 变量名规范赋值方式输入输出程序格式注释 基础语法元素 列表 序列类型a[1,2,3,4,5]元素有位置顺序&#xff0c;通过位置访问&#xff1a;a[0] 元组 序列类型元素不支持修改&#xff08;元组&#xff1a;不可变的列表&#xff09;a(1,2,3…