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

10. 怎么实现深拷贝?

总结

实现深拷贝的方式有多种,选择应根据具体需求:

  • 简单场景:使用 JSON.parse(JSON.stringify(obj))
  • 学习/教学:使用递归实现 + 循环引用处理
  • 生产环境:优先使用 lodash.cloneDeep
  • 浏览器端(现代):使用 structuredClone

建议:在开发中优先使用成熟的库(如 lodash),避免重复造轮子。如需自定义实现,应考虑特殊类型、循环引用、性能等问题。


概述

在 JavaScript 中,深拷贝是指创建一个新对象,使其与原对象完全独立,互不影响。与之相对的是浅拷贝,只复制引用地址,原对象和新对象共享内部引用的数据。

深拷贝常用于:

  • 状态快照保存(如撤销/重做功能)
  • 数据隔离(避免修改原始数据)
  • 跨组件通信时的数据传递

一、常见的深拷贝方式

1. 使用 JSON.parse(JSON.stringify(obj))(简单但有局限)

原理:

将对象序列化为 JSON 字符串,再解析为新对象。

示例:
const obj = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(obj));copy.b.c = 3;
console.log(obj.b.c); // 2(原对象未被修改)
优点:
  • 简洁、无需额外代码
  • 支持大多数基础结构
缺点:
限制说明
不支持函数、undefined会被忽略
不支持循环引用会报错
不支持 Symbol 属性键会被忽略
日期对象会被转为字符串无法还原为 Date 对象
正则表达式等特殊对象也会丢失RegExp

2. 递归实现深拷贝(基础实现)

示例:
function deepClone(obj) {if (obj === null || typeof obj !== "object") return obj;const copy = Array.isArray(obj) ? [] : {};for (const key in obj) {if (obj.hasOwnProperty(key)) {copy[key] = deepClone(obj[key]);}}return copy;
}
优点:
  • 可以处理对象、数组
  • 可扩展性强
缺点:
  • 不处理循环引用会栈溢出
  • 无法复制函数、DateRegExp 等特殊对象

3. 使用第三方库(推荐)

(1) lodashcloneDeep
npm install lodash
import _ from "lodash";const obj = { a: 1, b: { c: 2 } };
const copy = _.cloneDeep(obj);
(2) structuredClone(浏览器原生 API,现代浏览器支持)
const obj = { a: 1, b: { c: 2 } };
const copy = structuredClone(obj);

✅ 支持:DateMapSetArrayBufferError
❌ 不支持:函数、undefined、某些循环引用


二、处理循环引用的深拷贝实现

function deepClone(obj, visited = new Map()) {if (obj === null || typeof obj !== "object") return obj;if (visited.has(obj)) {return visited.get(obj); // 防止循环引用}const copy = Array.isArray(obj) ? [] : {};visited.set(obj, copy);for (const key in obj) {if (obj.hasOwnProperty(key)) {copy[key] = deepClone(obj[key], visited);}}return copy;
}

三、不同深拷贝方式对比

方法支持类型循环引用函数支持日期支持正则支持性能推荐场景
JSON.parse✅ 对象/数组⭐⭐⭐⭐简单对象,无特殊类型
递归实现✅ 对象/数组❌(需手动处理)⭐⭐学习用途
lodash.cloneDeep✅ 多种类型⭐⭐⭐⭐⭐生产环境
structuredClone✅ 多种类型⭐⭐⭐⭐浏览器端
手动封装(带类型判断)✅ 自定义✅(可实现)✅(可实现)✅(可实现)✅(可实现)⭐⭐⭐定制化需求

四、深拷贝的注意事项

说明
循环引用必须使用 MapWeakMap 缓存已拷贝对象
特殊对象DateRegExpMapSet 需要单独处理
函数通常不需要拷贝,直接返回原引用即可
Symbol 类型键需要用 Reflect.ownKeys 获取
原型链上的属性通常不需要拷贝,除非特别要求
性能优化深拷贝可能影响性能,应避免频繁调用

http://www.xdnf.cn/news/1268713.html

相关文章:

  • 【n8n】学习n8n【10】:Github的项目n8n-workflows:本地安装2,053 个 n8n 工作流程集合:随时看随时抄/学习~
  • 嵌入式 - Linux软件编程
  • 基于 RAUC 的 Jetson OTA 升级全攻略
  • 【文献阅读】我国生态问题鉴定与国土空间生态保护修复方向
  • 本地部署接入 whisper + ollama qwen3:14b 总结字幕
  • 【R语言】单细胞数据整合质量评估(3)
  • 初学python的我开始Leetcode题15-2
  • 【Python 工具人快餐 · 第 2 份】
  • TensorFlow深度学习实战(29)——强化学习(Reinforcement learning,RL)
  • Android 开发问题:The specified child already has a parent.
  • Visual Studio Code (v1.103) 中 GitHub Copilot 最新更新!
  • LLM表征的提取方式
  • n8n飞书webhook配置(飞书机器人、飞书bot、feishu bot)Crypto节点、js timestamp代码、Crypto node
  • 电机控制器母线电压采样芯片有哪些
  • 机器学习——模型的简单优化
  • 如何判断一个数是 2 的幂 / 3 的幂 / 4 的幂 / n 的幂 位运算 总结和思考 每日一题 C++的题解与思路
  • 机器翻译:需要了解的数学基础详解
  • 客服Agent革命:智能客服系统的技术实现与效果评估
  • Java Stream流详解:用法与常用API实战
  • Tob大客户销售面试经验
  • 数据安全与隐私保护:企业级防护策略与技术实现
  • DBSCAN聚类算法实战全解析
  • 时序分解 | MATLAB实现SAO-VMD雪消融算法优化变分模态分解
  • Python 属性描述符(描述符用法建议)
  • 词向量可视化:用TensorBoard或PCA探索词向量空间
  • RecyclerView 中 ViewHolder
  • Datawhale+AI夏令营_让AI读懂财报PDF task2深入赛题笔记
  • 学习Java的Day28
  • 常用信号深度解析(SIGINT、SIGPIPE、SIGALRM、SIGTERM等)
  • Android 锁屏图标的大小修改