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

手写深拷贝函数

在 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;
}

代码解析

  1. 基本数据类型处理

    • 如果 target 是基本数据类型(如 numberstringboolean 等)或者为 null,直接返回即可。
    • 这是因为基本数据类型是按值传递的,不需要深拷贝。
  2. 防止循环引用

    • 使用 WeakMap 来存储已经拷贝过的对象。
    • 如果发现当前对象已经在 map 中存在,则直接返回它的拷贝,避免无限递归。
  3. 初始化结果容器

    • 如果目标是一个数组,则初始化一个空数组。
    • 如果目标是一个对象,则初始化一个空对象。
  4. 递归拷贝

    • 遍历目标对象的所有属性(使用 for...inhasOwnProperty 检查自有属性)。
    • 对每个属性值递归调用 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(循环引用处理正确)

注意事项

  1. 性能问题

    • 深拷贝可能会消耗大量内存,特别是对于大型对象或数组。
    • 可以根据实际需求优化,例如只拷贝特定深度的对象。
  2. 特殊对象

    • 上述实现未考虑 DateRegExpMapSet 等特殊对象。
    • 如果需要支持这些类型,可以扩展代码逻辑。

支持特殊对象的改进版

以下是一个支持更多类型的深拷贝函数:

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 教程】
1Openlayers 【入门教程】 - 【源代码+示例 300+】
2Leaflet 【入门教程】 - 【源代码+图文示例 150+】
3MapboxGL【入门教程】 - 【源代码+图文示例150+】
4Cesium 【入门教程】 - 【源代码+综合教程 200+】
5threejs【中文API】 - 【源代码+图文示例200+】
6Shader 编程 【图文示例 100+】
7Geoserver 【配置教程 100+】
8卫星应用开发教程 【配置+应用教程 100+】
9GIS数字孪生与大模型 【应用实战 100+】
10报表与数字大屏 【Echarts 实战示例】 - 【D3 综合教程】 - 【其他大屏】
http://www.xdnf.cn/news/1340.html

相关文章:

  • 基于RabbitMQ实现订单超时自动处理
  • 服务器编译环境配置及数据接收脚本编写(11)
  • 蓝桥杯 19. 最大比例
  • 【3】CICD持续集成-k8s集群中安装Jenkins-agent(主从架构)
  • 【数据可视化-24】巧克力销售数据的多维度可视化分析
  • 解读大型语言模型:从Transformer架构到模型量化技术
  • 3小时速通Python-Python学习总部署、总预览(一)
  • transformer 解码器和输出部分结构
  • gradle可用的下载地址(免费)
  • Linux 内核中 cgroup 子系统 cpuset 是什么?
  • nodejs模块暴露数据的方式,和引入(导入方式)方式
  • 高级java每日一道面试题-2025年4月21日-基础篇[反射篇]-如何使用反射获取一个类的所有方法?
  • 移动通信运营商对MTU的大小设置需求
  • 【codeforces思维题】前缀和的巧妙应用(2053B)
  • 【AI News | 20250422】每日AI进展
  • 计算机组成原理---总线系统的详细概述
  • HCIP-H12-821 核心知识梳理 (5)
  • 如何修改文件termsrv.dll实现多用户同时远程
  • 一个关于相对速度的假想的故事-4
  • AGI大模型(12):向量检索之关键字搜索
  • 企业战略到数字化落地 —— 第四章 SOP 的概念
  • 几种电气绝缘类型
  • Mininet--node.py源码解析
  • 学习笔记——《Java面向对象程序设计》-抽象和接口
  • 实验1python基本网络应用
  • 为TA开发人员介绍具有最新改进的Kinibi-610a
  • 【Vue3 / TypeScript】 项目兼容低版本浏览器的全面指南
  • 【MySQL】数据库基础
  • 从马拉松到格斗大赛:人形机器人撕开的万亿市场,正在改写AI规则
  • STM32单片机入门学习——第45节: [13-2] 修改频主睡眠模式停止模式待机模式