深拷贝在 JavaScript 中的几种实现方式对比
深拷贝在 JavaScript 中的几种实现方式对比
- 1. JSON 序列化法
- 2. 结构化克隆(structuredClone)
- 原理与使用
- 3. 自定义深拷贝函数
- 原理与使用
- 性能对比与选择建议
- 性能比较
- 综合建议:
- 示例代码整合
- 总结
在开发过程中,我们经常需要对对象进行深拷贝,以便创建一个数据的完全独立副本,避免不小心修改原始数据。常见的深拷贝方法有以下几种:
• JSON 序列化法(JSON.stringify/JSON.parse)
• 结构化克隆(structuredClone)
• 自定义深拷贝函数
下面将详细介绍每种方法,并讨论它们在效率和适用场景上的不同。
1. JSON 序列化法
原理与使用
通过 JSON.stringify() 将对象转为 JSON 字符串,再利用 JSON.parse() 还原为新对象。例如:
const deepCopyJson = (obj) => {return JSON.parse(JSON.stringify(obj));
};
优点:
• 实现简单,代码少。
• 对于简单对象(不包含函数、undefined、Symbol、循环引用等)非常有效。
缺点:
• 无法处理特殊数据类型:例如 Date、RegExp、Map、Set、undefined、Infinity 等会丢失或转换不正确。
• 当对象数据量较大时,序列化和反序列化过程可能比较耗时。
• 对于包含循环引用的对象会抛错。
适用场景:
加粗样式 • 对象结构简单,数据格式固定时(例如配置数据或简单的 JSON 数据)。
2. 结构化克隆(structuredClone)
原理与使用
现代浏览器提供了原生的 structuredClone() 方法,利用浏览器内部优化的结构化克隆算法,能够高效地复制多种复杂数据结构。使用示例:
if (typeof structuredClone === 'function') {const newObj = structuredClone(obj);
}
优点:
• 原生支持,效率较高,尤其适用于大型或复杂对象。
• 能够处理更多类型的数据:如 Map、Set、ArrayBuffer、Date 等。
• 内部实现针对循环引用也能较好地处理。
缺点:
• 浏览器兼容性需要注意,老旧环境可能不支持。
• 对于小对象,可能没有明显优势,有时反而比 JSON 方法稍慢(不过整体差异不大)。
适用场景:
• 对象结构复杂或包含特殊数据类型时;
• 对性能有较高要求且运行环境支持该 API 时。
3. 自定义深拷贝函数
原理与使用
在无法使用 JSON 或 structuredClone 的情况下,可以手动编写递归函数来深度拷贝对象。下面是一个简单的实现:
const deepCopy = (item) => {if (item === null || typeof item !== 'object') {return item;}if (Array.isArray(item)) {return item.map(deepCopy);}const result = {};for (const key in item) {if (Object.prototype.hasOwnProperty.call(item, key)) {result[key] = deepCopy(item[key]);}}return result;
};const newObj = deepCopy(obj);
优点:
• 灵活性高,可以根据需要扩展以处理更多特殊情况。
• 不依赖环境提供的 API,兼容性好。
缺点:
• 需要手动处理各种边界情况,代码实现和维护较复杂。
• 性能上通常不及浏览器原生实现的 structuredClone。
适用场景:
• 对兼容性有要求的项目或需要定制拷贝逻辑的场景;
• 数据结构较简单,且不频繁调用时。
性能对比与选择建议
性能比较
- 小型对象:
JSON 方法通常性能较好,因为序列化过程开销较低,且实现简单。 - 复杂对象:
对于包含特殊数据类型或嵌套层次较深的对象,structuredClone 通常表现更优,因为它是浏览器内部实现的,并针对复杂场景做了优化。 - 自定义函数:
一般来说,自定义递归实现的性能不及结构化克隆,但可以针对具体需求进行优化。
综合建议:
- 优先选择 JSON 方法:当你确定对象数据格式简单,并且不会包含无法序列化的内容时。
- 考虑 structuredClone:如果运行环境支持且对象较大或结构复杂,使用 structuredClone() 更能保证数据完整性和性能。
- 自定义深拷贝:当需要对数据进行特殊处理或兼容不支持 structuredClone 的环境时,可以采用自定义函数,但要注意性能优化和代码健壮性。
示例代码整合
下面给出一个综合示例,根据对象大小自动选择拷贝方式,并在异常时捕获错误:
function efficientDeepCopy(obj) {try {if (!obj) return {};// 对于小型对象,使用 JSON 方法可能更快if (JSON.stringify(obj).length < 10000) {return JSON.parse(JSON.stringify(obj));}// 使用结构化克隆(如果可用)if (typeof structuredClone === 'function') {return structuredClone(obj);}// 自定义深拷贝函数,处理常见数据类型const deepCopy = (item) => {if (item === null || typeof item !== 'object') {return item;}if (Array.isArray(item)) {return item.map(deepCopy);}const result = {};for (const key in item) {if (Object.prototype.hasOwnProperty.call(item, key)) {result[key] = deepCopy(item[key]);}}return result;};return deepCopy(obj);} catch (error) {console.error('efficientDeepCopy error:', error);return {};}
}
在这个示例中,根据对象序列化后的长度来判断是否使用 JSON 方法;如果对象较大且环境支持 structuredClone,则优先使用它;否则回退到自定义深拷贝函数。
总结
- JSON 方法:适用于简单数据,性能好,但局限性明显。
- structuredClone:适用于复杂和大型对象,兼容性需要关注,但总体性能较高。
- 自定义深拷贝:灵活但复杂,一般作为最后的备用方案。
通过对比,可以根据项目的具体需求和对象的特点,选择最合适的深拷贝方式,从而在性能与功能之间取得平衡。
相关文章:
深拷贝在 JavaScript 中的几种实现方式对比
深拷贝在 JavaScript 中的几种实现方式对比 1. JSON 序列化法2. 结构化克隆(structuredClone)原理与使用 3. 自定义深拷贝函数原理与使用 性能对比与选择建议性能比较 综合建议:示例代码整合总结 在开发过程中,我们经常需要对对象…...
实验11 机器学习-贝叶斯分类器
实验11 机器学习-贝叶斯分类器 一、实验目的 (1)理解并熟悉贝叶斯分类器的思想和原理; (2)熟悉贝叶斯分类器的数学推导过程; (3)能运用贝叶斯分类器解决实际问题并体会算法的效果&a…...
Delta Lake 解析:架构、数据处理流程与最佳实践
Delta Lake 是一个基于 Apache Spark 的开源存储层,主要解决传统数据湖(Data Lake)缺乏 ACID 事务、数据一致性和性能优化的问题,使大数据处理更加可靠、高效。从本质上讲,它让数据湖具备了数据仓库的结构化管理能力&a…...
OpenHarmony子系统开发 - 电池管理(二)
OpenHarmony子系统开发 - 电池管理(二) 五、充电限流限压定制开发指导 概述 简介 OpenHarmony默认提供了充电限流限压的特性。在对终端设备进行充电时,由于环境影响,可能会导致电池温度过高,因此需要对充电电流或电…...
hive 数据简介
Hive介绍 1)Hive简介 Hive是基于Hadoop的一个数据仓库工具,用于结构化数据的查询、分析和汇总。Hive提供类SQL查询功能,它将SQL转换为MapReduce程序。 Hive不支持OLTP,Hive无法提供实时查询。 2)Hive在大数据生态环境…...
Win32桌面编程:ACLUI.DLL,EditSecurity(IntPtr hwndOwner, ISecurityInformation psi)
在Windows编程中,我们通常需要借助通用对话框的力量,今天我们就聊一下“安全属性表”通用对话框的使用心得。 当我们调用EditSecurity函数时: 1.EditSecurity将调用ISecurityInformation中的GetObjectInformation函数 在编写 ISecurityInf…...
数据分析异步进阶:aiohttp与Asyncio性能提升
一、时间轴呈现方案进程 2023-04-01:需求确认 确定目标:使用aiohttp与Asyncio提升采集性能,目标采集今日头条网站的新闻数据(标题、内容、时间等)。同时要求在程序中加入代理IP、Cookie和UserAgent的设置,…...
《AI大模型趣味实战 》第8集:多端适配 个人新闻头条 基于大模型和RSS聚合打造个人新闻电台(Flask WEB版) 2
《AI大模型趣味实战 》第8集:多端适配 个人新闻头条 基于大模型和RSS聚合打造个人新闻电台(Flask WEB版) 2 摘要 本文末尾介绍了如何实现新闻智能体的方法。在信息爆炸的时代,如何高效获取和筛选感兴趣的新闻内容成为一个现实问题。本文将带领读者通过P…...
低配电脑畅玩《怪物猎人:荒野》,ToDesk云电脑优化从30帧到144帧?
《怪物猎人:荒野(Monster Hunter Wilds)》自2025年正式发售以来已取得相当亮眼的成绩,仅用三天时间便轻松突破800万销量,目前顺利蝉联周榜冠军;凭借着开放世界的宏大场景和丰富的狩猎玩法,该游戏…...
Leetcode刷题笔记1 图论part03
卡码网 101 孤岛总面积 from collections import deque directions [[0, 1], [1, 0], [0, -1], [-1, 0]] count 0def main():global countn, m map(int, input().split())grid []for _ in range(n):grid.append(list(map(int, input().split())))for i in range(n):if gri…...
【模拟面试】计算机考研复试集训(第十一天)
文章目录 前言一、专业面试1、什么是面向对象编程?2、软件工程的主要模型有哪些?3、Cache和寄存器的区别4、卷积层有哪些参数,它们代表什么?5、你有读博的打算吗?6、你的师兄/姐临近毕业,仍做不出成果&…...
查看自己的公有ip
IP 地址 112.3.88.1** 是一个 公有 IP 地址,而不是私有 IP 地址。 公有 IP 地址 vs 私有 IP 地址 公有 IP 地址: 用于在互联网上唯一标识设备。由互联网服务提供商(ISP)分配。可以在全球范围内路由和访问。例如:112.3.88.156、8.8…...
【js逆向入门】图灵爬虫练习平台 第九题
地址:aHR0cHM6Ly9zdHUudHVsaW5ncHl0b24uY24vcHJvYmxlbS1kZXRhaWwvOS8 f12进入了debugger,右击选择一律不在此处暂停, 点击继续执行 查看请求信息 查看载荷,2个加密参数,m和tt 查看启动器,打上断点 进来 往…...
NET6 WebApi第5讲:中间件(源码理解,俄罗斯套娃怎么来的?);Web 服务器 (Nginx / IIS / Kestrel)、WSL、SSL/TSL
一、NET6的启动流程 区别: .NET6 WebApi第1讲:VSCode开发.NET项目、区别.NET5框架【两个框架启动流程详解】_vscode webapi-CSDN博客 2、WebApplicationBuilder:是NET6引入的一个类,是建造者模式的典型应用 1>建造者模式的…...
Nginx及前端部署全流程:初始化配置到生产环境部署(附Nginx常用命令)
nginx&前端从初始化配置到部署(xshell) 前言下载nginx前端打包与创建具体文件夹路径配置nginx.nginx.conf文件配置项内容 配置nginx.service文件配置项内容 启动nginx常用nginx命令 前言 目标:在xshell中部署前端包。 第一步:…...
python 实现一个简单的window 任务管理器
import tkinter as tk from tkinter import ttk import psutil# 运行此代码前,请确保已经安装了 psutil 库,可以使用 pip install psutil 进行安装。 # 由于获取进程信息可能会受到权限限制,某些进程的信息可能无法获取,代码中已经…...
【AI模型】深度解析:DeepSeek的联网搜索的实现原理与认知误区
一、大模型的“联网魔法”:原来你是这样上网的! 在人工智能这个舞台上,大模型们可是妥妥的明星。像DeepSeek、QWen这些大模型,个个都是知识渊博的“学霸”,推理、生成文本那叫一个厉害。不过,要是论起上网…...
【xiaozhi赎回之路-2:语音可以自己配置就是用GPT本地API】
固件作用 打通了网络和硬件的沟通 修改固件实现【改变连接到小智服务器的】 回答逻辑LLM自定义 自定义了Coze(比较高级,自定义程度比较高,包括知识库,虚拟脚色-恋人-雅思老师-娃娃玩具{可能需要使用显卡对开源模型进行微调-产…...
WX小程序
下载 package com.sky.utils;import com.alibaba.fastjson.JSONObject; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.Cl…...
JavaScript案例0322
以下是一些涵盖不同高级JavaScript概念和应用的案例,每个案例都有详细解释: 案例1:实现 Promise/A 规范的手写 Promise class MyPromise {constructor(executor) {this.state pending;this.value undefined;this.reason undefined;this.o…...
Spring boot 3.4 后 SDK 升级,暨 UI API/MCP 计划
PS 写这篇文章后看到 A Deep Dive Into MCP and the Future of AI Tooling | Andreessen HorowitzWe explore what MCP is, how it changes the way AI interacts with tools, what developers are already building, and the challenges that still need solving. https://a1…...
大数据学习(78)-spark streaming与flink
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
2.企业级AD活动目录架构与设计原则实战指南
一、企业级AD架构核心组件解析 1.1 多域森林架构设计 核心概念: 单域模型:适用于中小型企业(<5万用户) 多域模型:满足跨国/多部门隔离需求 森林(Forest):安全信任边界&#x…...
Linux下JDK1.8安装配置
目录 1.下载完上传到Linux系统中 2.解压JDK压缩包 3.配置JDK环境变量 4.设置环境变量生效 5.查看环境变量是否配置成功 官网下载地址:Java Downloads | Oracle 1.下载完上传到Linux系统中 2.解压JDK压缩包 tar -zxvf jdk-8u151-linux-x64.tar.gz -C /usr/local (解压…...
Python OCR文本识别详细步骤及代码示例
光学字符识别(OCR)是将图像中的文字转换为可编辑文本的技术。在Python中,我们可以利用多种库实现OCR功能。本文将详细介绍使用Tesseract和EasyOCR进行文本识别的步骤,并提供完整的代码示例。 一、OCR简介 OCR(Optical…...
OpenCV 基础模块 Python 版
OpenCV 基础模块权威指南(Python 版) 一、模块全景图 plaintext OpenCV 架构 (v4.x) ├─ 核心层 │ ├─ core:基础数据结构与操作(Mat/Scalar/Point) │ └─ imgproc:图像处理流水线(滤…...
华为HCIE网络工程师培训选机构攻略
从 官方授权机构 到 性价比黑马,结合价格、师资、通过率等维度,为你筛选出最适合的培训方案。 一、华为官方授权机构(优先推荐) 华为官方授权机构拥有 真机实验环境考官级讲师,适合预算充足、追求高通过率的学员。 机…...
Linux固定IP方法(RedHat+Net模式)
1、查看当前网关 ip route | grep default 2、配置静态IP 双击重启 3、验证...
210、【图论】课程表(Python)
题目 思路 这道题本质上是一个拓扑排序。每次先统计每个点的入度个数、然后再统计点与点之间的邻接关系,找到入度为0的点作为起始遍历点。之后每遍历到这个点之后,就把这个点后续的邻接关系边的点入度减去一。当某个点入度为0时,继续被加入其…...
使用Python开发自动驾驶技术:车道线检测模型
友友们好! 我是Echo_Wish,我的的新专栏《Python进阶》以及《Python!实战!》正式启动啦!这是专为那些渴望提升Python技能的朋友们量身打造的专栏,无论你是已经有一定基础的开发者,还是希望深入挖掘Python潜力的爱好者,这里都将是你不可错过的宝藏。 在这个专栏中,你将会…...
