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

手写深拷贝函数

在 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 综合教程】 - 【其他大屏】

相关文章:

  • 【C语言-选择排序算法】实现对十个数进行排序
  • ubuntu24设置拼音输入法,解决chrome不能输入中文
  • 排序(C)
  • NLP高频面试题(五十二)——BERT 变体详解
  • Docker Python 官方镜像使用说明(TAG说明)
  • vim的.vimrc配置
  • 前端加密介绍与实战
  • 46. 全排列
  • Mysql之存储过程
  • 多源数据集成技术分析与应用实践探索
  • DeepSeek在物联网设备中的应用:通过轻量化模型实现本地化数据分析
  • 达妙电机CAN通信及实验
  • 努比亚Z70S Ultra 摄影师版将于4月28日发布,首发【光影大师990】传感器
  • GPLT-2025年第十届团体程序设计天梯赛总决赛题解(共计266分)
  • Go全栈_Golang、Gin实战、Gorm实战、Go_Socket、Redis、Elasticsearch、微服务、K8s、RabbitMQ全家桶
  • Laravel 自定义 Artisan 命令行
  • Qt案例 使用QFtpServerLib开源库实现Qt软件搭建FTP服务器,使用QFTP模块访问FTP服务器
  • TORL:解锁大模型推理新境界,强化学习与工具融合的创新变革
  • 第六章 QT基础:3、QT的打包和部署
  • 在串的简单模式匹配中,当模式串位j与目标串位i比较时,两字符不相等,则i的位移方式是?
  • 上海市统计局:经济运行开局平稳,高质量发展扎实推进
  • 降低血压可减少痴呆症发生风险
  • 委托第三方可一次性补缴十多万元的多年社保?广州多人涉嫌被骗后报警
  • 吉祥航空去年净利增超17%,海航实控人方威退出前十大股东
  • 对话地铁读书人|财务管理孟先生:老婆让我看《三体》
  • 外媒:罗马教皇方济各去世