手写深拷贝函数
在 JavaScript 中,深拷贝是指创建一个对象或数组的完全独立副本,包括其嵌套的对象或数组。这意味着修改副本不会影响原始对象。

以下是手写一个通用的深拷贝函数的实现:
深拷贝函数实现
function deepClone(target, map = new WeakMap()) {// 如果目标是基本数据类型,直接返回if (typeof target !== 'object' || target === null) {return target;}// 防止循环引用if (map.has(target)) {return map.get(target);}// 初始化结果容器const cloneTarget = Array.isArray(target) ? [] : {};// 将当前对象存入 map 中map.set(target, cloneTarget);// 遍历目标对象的所有属性for (const key in target) {if (target.hasOwnProperty(key)) {cloneTarget[key] = deepClone(target[key], map); // 递归深拷贝}}return cloneTarget;
}
代码解析
-
基本数据类型处理
- 如果
target是基本数据类型(如number、string、boolean等)或者为null,直接返回即可。 - 这是因为基本数据类型是按值传递的,不需要深拷贝。
- 如果
-
防止循环引用
- 使用
WeakMap来存储已经拷贝过的对象。 - 如果发现当前对象已经在
map中存在,则直接返回它的拷贝,避免无限递归。
- 使用
-
初始化结果容器
- 如果目标是一个数组,则初始化一个空数组。
- 如果目标是一个对象,则初始化一个空对象。
-
递归拷贝
- 遍历目标对象的所有属性(使用
for...in和hasOwnProperty检查自有属性)。 - 对每个属性值递归调用
deepClone,确保嵌套的对象和数组也能被深拷贝。
- 遍历目标对象的所有属性(使用
测试代码
// 测试对象
const obj = {name: 'Alice',age: 25,hobbies: ['reading', 'coding'],details: {address: 'Wonderland',phone: 123456789},circularRef: null // 循环引用
};
obj.circularRef = obj; // 设置循环引用// 深拷贝
const clonedObj = deepClone(obj);console.log(clonedObj);
console.log(clonedObj === obj); // false
console.log(clonedObj.details === obj.details); // false
console.log(clonedObj.hobbies === obj.hobbies); // false
console.log(clonedObj.circularRef === clonedObj); // true(循环引用处理正确)
注意事项
-
性能问题
- 深拷贝可能会消耗大量内存,特别是对于大型对象或数组。
- 可以根据实际需求优化,例如只拷贝特定深度的对象。
-
特殊对象
- 上述实现未考虑
Date、RegExp、Map、Set等特殊对象。 - 如果需要支持这些类型,可以扩展代码逻辑。
- 上述实现未考虑
支持特殊对象的改进版
以下是一个支持更多类型的深拷贝函数:
function deepClone(target, map = new WeakMap()) {// 基本数据类型和 nullif (typeof target !== 'object' || target === null) {return target;}// 特殊对象处理const constructor = target.constructor;if (/^(Date|RegExp|Map|Set)$/i.test(constructor.name)) {return new constructor(target);}// 防止循环引用if (map.has(target)) {return map.get(target);}// 初始化结果容器const cloneTarget = Array.isArray(target) ? [] : {};map.set(target, cloneTarget);// 遍历目标对象的所有属性for (const key in target) {if (target.hasOwnProperty(key)) {cloneTarget[key] = deepClone(target[key], map);}}return cloneTarget;
}
通过上述方法,你可以实现一个功能完善的深拷贝函数,并根据实际需求进行扩展!
| No. | 大剑师精品GIS教程推荐 |
|---|---|
| 0 | 地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 |
| 1 | Openlayers 【入门教程】 - 【源代码+示例 300+】 |
| 2 | Leaflet 【入门教程】 - 【源代码+图文示例 150+】 |
| 3 | MapboxGL【入门教程】 - 【源代码+图文示例150+】 |
| 4 | Cesium 【入门教程】 - 【源代码+综合教程 200+】 |
| 5 | threejs【中文API】 - 【源代码+图文示例200+】 |
| 6 | Shader 编程 【图文示例 100+】 |
| 7 | Geoserver 【配置教程 100+】 |
| 8 | 卫星应用开发教程 【配置+应用教程 100+】 |
| 9 | GIS数字孪生与大模型 【应用实战 100+】 |
| 10 | 报表与数字大屏 【Echarts 实战示例】 - 【D3 综合教程】 - 【其他大屏】 |
相关文章:
手写深拷贝函数
在 JavaScript 中,深拷贝是指创建一个对象或数组的完全独立副本,包括其嵌套的对象或数组。这意味着修改副本不会影响原始对象。 以下是手写一个通用的深拷贝函数的实现: 深拷贝函数实现 function deepClone(target, map new WeakMap()) {//…...
React 性能优化三剑客实战:告别无效重渲染!
在 Vue 中我们可能依赖 Vuex computed 进行状态共享和性能优化,而在 React 里呢?不需要用 Redux,靠 useContext、memo、useMemo 三剑客就能构建高性能组件通信方案! 🧩 useContext 再回顾:状态共享不等于性…...
深度学习3.3 线性回归的简洁实现
步骤操作作用前向计算net(X)计算预测值 y_hat Xw b损失计算loss(y_hat, y)量化预测误差,驱动参数更新反向传播l.backward()计算参数梯度参数更新trainer.step()根据梯度调整参数,逼近最优解梯度清零trainer.zero_grad()防止梯度累积(必须放…...
复盘20250422
深度分析及个股推荐 1. 行业前景与个股逻辑梳理 从提供的股票信息来看,主要涉及以下行业:合成尼古丁(电子烟)、化工、跨境支付、跨境电商、农药、食品饮料、光刻机、电子商务、造纸等。需结合行业景气度、政策支持、公司核心竞争…...
从零开始学习MySQL的系统学习大纲
文章目录 前言第一阶段:数据库与 MySQL 基础认知数据库基础概念MySQL 简介 第二阶段:MySQL 安装与环境搭建安装前的准备MySQL 安装过程安装后的配置 第三阶段:SQL 基础语法SQL 概述数据库操作数据表操作数据操作 第四阶段:SQL 高级…...
APP动态交互原型实例|墨刀变量控制+条件判断教程
引言 不同行业的产品经理在绘制原型图时,拥有不同的呈现方式。对于第三方软件技术服务公司的产品经理来说,高保真动态交互原型不仅可以在开发前验证交互逻辑,还能为甲方客户带来更直观、真实的体验。 本文第三部分将分享一个实战案例&#…...
基于控制台的小车导航游戏开发详解(C++实现)
本文将详细讲解一个基于C控制台的小车导航游戏项目。通过该项目可以学习二维数组操作、队列数据结构应用以及游戏循环控制等核心编程概念,特别适合刚接触游戏开发的初学者学习。 一、项目概述 1.1 游戏规则 玩家可创建多辆具有不同初始位置和移动速度的小车 每辆…...
色谱图QCPColorMap
一、QCPColorMap 概述 QCPColorMap 是 QCustomPlot 中用于绘制二维颜色图的类,可以将矩阵数据可视化为颜色图(热力图),支持自定义色标和插值方式。 二、主要属性 属性类型描述dataQCPColorMapData存储颜色图数据的对象interpol…...
大文件分片上传进阶版(新增md5校验、上传进度展示、并行控制,智能分片、加密上传、断点续传、自动重试),实现四位一体的网络感知型大文件传输系统
上篇文章我们总结了大文件分片上传的主要核心,但是我对md5校验和上传进度展示这块也比较感兴趣,所以在deepseek的帮助下,扩展了一下我们的代码,如果有任何问题和想法,非常欢迎大家在评论区与我交流,我需要学…...
oracle不同数据库版本的自增序列
-- 查看数据库版本 SELECT * FROM v$version WHERE banner LIKE Oracle%; 1. Oracle 12c及以上版本支持 id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, id NUMBER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) PRIMARY KEY, -- 语法 id NUMBER GENER…...
【KWDB创作者计划】_针对KWDB时序数据库(多副本集群环境)进行压力测试
【KWDB创作者计划】_针对KWDB时序数据库(多副本集群环境)进行压力测试 1. 概述2. 压测环境部署3. 生成测试数据4. 写入性能测试5. 查询性能测试7. 总结 1. 概述 KaiwuDB分布式多模数据库从物联网场景真实需求出发,针对性设计多模架构。物联网…...
极狐GitLab 自定义实例级项目模板功能介绍
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 自定义实例级项目模板 (PREMIUM SELF) 极狐GitLab 管理员可以将群组设置为在实例上创建新项目时可选择的项目模板的来源。然…...
最新扣子(Coze)案例教程:飞书多维表格按条件筛选记录 + 读取分页Coze工作流,无限循环使用方法,手把手教学,完全免费教程
大家好,我是斜杠君。 👨💻 星球群里有同学想学习一下飞书多维表格的使用方法,关于如何通过按条件筛选飞书多维表格中的记录,以及如何使用分页解决最多一次只能读取500条的限制问题。 斜杠君今天就带大家一起搭建一…...
第八天 AI开发:NavMesh导航系统 对话系统:使用ScriptableObject存储对话数据 存档系统:JSON序列化保存数据
一、智能导航系统:NavMesh实战指南 1.1 导航网格基础配置 在Unity编辑器中: 选择场景中的静态物体勾选Navigation Static属性打开Window > AI > Navigation窗口 烘焙参数设置: NavMeshBuildSettings settings NavMesh.GetSettingsBy…...
Spring AI Alibaba-02-多轮对话记忆、持久化消息记录
Spring AI Alibaba-02-多轮对话记忆、持久化消息记录 Lison <dreamlison163.com>, v1.0.0, 2025.04.19 文章目录 Spring AI Alibaba-02-多轮对话记忆、持久化消息记录多轮对话对话持久-Redis 本次主要聚焦于多轮对话功能的实现,后续会逐步增加更多实用内容&…...
联邦元学习实现个性化物联网的框架
随着数据安全和隐私保护相关法律法规的出台,需要直接在中央服务器上收集和处理数据的集中式解决方案,对于个性化物联网而言,训练各种特定领域场景的人工智能模型已变得不切实际。基于此,中山大学,南洋理工大学…...
做虚拟化应该怎么选择美国服务器?
选择适合做虚拟化的美国服务器,需要综合考虑硬件性能、网络质量、稳定性、价格和服务支持等多个方面。以下是详细的选购指南,适合准备搭建VPS、虚拟主机、分销业务、开发测试环境、容器集群等用途的用户参考。 一、为什么美国服务器适合虚拟化? 美国机房…...
实验1 温度转换与输入输出强化
知识点:input()/print()、分支语句、字符串处理(教材2.1-2.2) 实验任务: 1. 实现摄氏温度与华氏温度互转(保留两位小数) 2. 扩展功能:输入错误处理(如非数字输入提示重新输入&#x…...
MongoDB 集合名称映射问题
项目场景 在使用 Spring Data MongoDB 进行开发时,定义了一个名为 CompetitionSignUpLog 的实体类,并创建了对应的 Repository 接口。需要明确该实体类在 MongoDB 中实际对应的集合名称是 CompetitionSignUpLog 还是 competitionSignUpLog。 问题描述 …...
【AI】SpringAI 第五弹:接入千帆大模型
1. 添加依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-qianfan</artifactId> </dependency> 2. 编写 yml 配置文件 spring:ai:qianfan:api-key: 你的api-keysecret-key: 你的secr…...
【编码规范】原生开发 与 Vue+组件库开发
原生开发 vs Vue组件库开发对比 一、原生开发常用方法 DOM操作: document.getElementById()document.querySelector()element.addEventListener()classList API操作类名 事件处理: 直接事件绑定事件委托 document.body.addEventListener(click, functi…...
[Godot] C#2D平台游戏基础移动和进阶跳跃代码
本文章给大家分享一下如何实现基本的移动和进阶的跳跃(跳跃缓冲、可变跳跃、土狼时间)以及相对应的重力代码,大家可以根据自己的需要自行修改 实现效果 场景搭建 因为Godot不像Unity,一个节点只能绑定一个脚本,所以我…...
【Unity笔记】Unity + OpenXR项目无法启动SteamVR的排查与解决全指南
图片为AI生成 一、前言 随着Unity在XR领域全面转向OpenXR标准,越来越多的开发者选择使用OpenXR来构建跨平台的VR应用。但在项目实际部署中发现:打包成的EXE程序无法正常启动SteamVR,或者SteamVR未能识别到该应用。本文将以“Unity OpenXR …...
使用 rebase 轻松管理主干分支
前言 最近遇到一个技术团队的 dev 环境分支错乱,因为是多人合作大家各自提交信息,导致出现很多交叉合并记录,让对应 log 看起来非常混乱,难以阅读。 举例说明 假设我们有一个项目,最初develop分支有 3 个提交记录&a…...
【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! …...
HttpSessionListener 的用法笔记250417
HttpSessionListener 的用法笔记250417 以下是关于 HttpSessionListener 的用法详解,涵盖核心方法、实现步骤、典型应用场景及注意事项,帮助您全面掌握会话(Session)生命周期的监听与管理: 1. 核心功能 HttpSessionLi…...
火山RTC 5 转推CDN 布局合成规则
实时音视频房间,转推CDN,文档: 转推直播--实时音视频-火山引擎 一、转推CDN 0、前提 * 在调用该接口前,你需要在[控制台](https://console.volcengine.com/rtc/workplaceRTC)开启转推直播功能。<br> * 调…...
Spark两种运行模式与部署
1. Spark 的运行模式 部署Spark集群就两种方式,单机模式与集群模式 单机模式就是为了方便开发者调试框架的运行环境。但是生产环境中,一般都是集群部署。 现在Spark目前支持的部署模式: (1)Local模式:在本地…...
react 父子组件通信 子 直接到父, 父 forwardref子
React核心概念:单向数据流(Unidirectional Data Flow) React 中数据的流动像瀑布一样,只能从上层组件(父组件)流向下层组件(子组件)。 子组件无法直接反向修改父组件的数据&#x…...
qt画一朵花
希望大家的生活都更加美好,画一朵花送给大家 效果图 void FloatingArrowPubshButton::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHints(QPainter::Antialiasing);QPen pen;pen.setColor("green");pen.setWidth(5);QBrush…...
