如何实现JavaScript深拷贝_有哪些方法可以避免引用问题


JavaScript深拷贝的核心是创建完全独立的新对象以避免引用问题;常用方法包括JSON.parse(JSON.stringify())(简洁但有类型限制)、structuredClone()(现代原生推荐)、递归手写(完全可控)和Lodash的_.cloneDeep()(生产环境稳妥)。

JavaScript 中实现深拷贝的核心目标是创建一个与原对象完全独立的新对象,确保修改副本不会影响原始数据。引用问题(比如修改嵌套对象时意外改变原对象)通常源于浅拷贝或直接赋值,而深拷贝能彻底切断引用链。

JSON.parse(JSON.stringify()) —— 简单但有局限

这是最常用、写法最简洁的深拷贝方式,适合纯数据对象(只含字符串、数字、布尔值、null、数组、普通对象):

  • ✅ 优点:一行代码搞定,性能尚可,兼容性好
  • ❌ 缺点:会丢失函数、undefined、Symbol、Date、RegExp、Map、Set、BigInt 等类型;循环引用直接报错;不能处理原型链和不可枚举属性
  • ⚠️ 示例:const copy = JSON.parse(JSON.stringify(original));

structuredClone() —— 现代浏览器推荐方案

ES2025 引入的原生 API,支持更多数据类型,且能正确处理 Date、RegExp、Map、Set、ArrayBuffer、TypedArray 等:

  • ✅ 优点:原生、安全、语义清晰、支持大部分结构化数据
  • ❌ 缺点:目前不支持函数、undefined、Symbol、循环引用(仍会抛错),且在 Node.js 17+ 和较新浏览器中才可用
  • ⚠️ 示例:const copy = structuredClone(original);

递归手写深拷贝 —— 完全可控,适合复杂场景

当需要支持函数、自定义类型、循环引用或特殊逻辑时,需手动实现。关键点包括类型判断、递归遍历、缓存已拷贝对象(解决循环引用):

  • typeofObject.prototype.toString.call() 准确识别类型(如 Array、Date、RegExp、Map、Set)
  • 维护一个 WeakMap 记录源对象 → 拷贝对象的映射,遇到重复引用直接返回已有拷贝
  • 对普通对象和数组递归处理每个键值;对特殊类型(如 Date)调用构造器新建实例
  • ⚠️ 注意:不处理原型链上的属性,默认只拷贝自身可枚举属性(类似 Object.assign 行为)

Lodash 的 _.cloneDeep() —— 生产环境稳妥选择

经过大量测试的成熟工具函数,覆盖绝大多数边界情况(包括函数、循环引用、稀疏数组、不可枚举属性等):

  • ✅ 优点:健壮、文档完善、社区验证充分、支持自定义克隆逻辑(通过 customizer)
  • ❌ 缺点:引入额外依赖,包体积增加;部分场景略重(如仅需简单拷贝)
  • ⚠️ 使用:import { cloneDeep } from 'lodash-es'; const copy = cloneDeep(original);

选择哪种方法取决于你的运行环境、数据结构复杂度和是否允许第三方依赖。日常开发中,优先考虑 structuredClone()(兼容性满足时),否则用 Lodash;临时调试或简单数据可用 JSON 方案;需要极致控制或学习原理,就动手写递归版本。


# javascript  # java  # js  # node.js  # json  # node  # 浏览器  # 工具  # red 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: Python安全爬虫设计_IP代理池与验证码识别策略解析  Bpmn 2.0的XML文件怎么画流程图  mac怎么查看wifi密码_MAC查看已连接WiFi密码方法【技巧】  Windows10电脑怎么设置文件权限_Win10安全选项卡所有者修改  Windows10系统怎么查看CPU温度_Win10性能监视器查看硬件数据  Windows10电脑怎么设置电源按钮_Win10按电源键关机或休眠  Win11怎么禁用键盘自带键盘_Win11笔记本禁用内置键盘方法【教程】  php中::能访问全局变量吗_全局作用域与类作用域区分【操作】  Mac怎么设置鼠标滚动速度_Mac鼠标设置详细参数  Win11怎么设置快速访问_Windows11文件资源管理器主页  Win11怎样安装网易云音乐_Win11安装网易云教程【步骤】  如何使用Golang操作指针变量_Golang解引用与赋值实践  Win11怎么关闭自动维护 Win11禁用系统自动维护功能【优化】  Windows电脑键盘突然失灵怎么办?(驱动与硬件排查)  Windows如何拦截腾讯视频广告_Windows拦截腾讯视频广告方法【方法】  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  Win11如何设置电源计划_Win11电源计划优化教程【攻略】  Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置  php中常量能用::访问吗_类常量与作用域操作符使用场景【汇总】  Win11怎么关闭OneDrive同步_Win11取消自动备份文件【教程】  如何解决Windows字体显示模糊的问题?(ClearType设置)  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  c++如何用AFL++进行模糊测试 c++ Fuzzing入门【安全】  Windows 10怎么录屏_Windows 10使用Xbox Game Bar录制屏幕视频教程  c++ stringstream用法详解_c++字符串与数字转换利器  Win11怎么查看显卡显存_查询Win11显卡详细参数方法【步骤】  php8.4如何配置ssl证书_php8.4https访问配置指南【教程】  Python对象比较与排序_魔术方法解析【教程】  如何在 Go 项目开发中正确处理本地包导入与远程模块路径的一致性问题  Python装饰器设计思路_功能增强机制说明【指导】  如何在Golang中实现WebSocket广播_使用Channel和协程分发消息  c++怎么调用nana库开发GUI_c++ 现代风格窗口组件与事件处理【实战】  Win10如何优化内存使用_Win10内存优化技巧【攻略】  php怎么下载安装并配置环境变量_命令行调用PHP技巧【技巧】  Win11开机速度慢怎么优化_Win11系统启动加速设置指南【方法】  如何在Golang中实现文件下载_Golang文件传输与内容类型处理方法  Windows 11如何开启文件夹加密(EFS)_Windows 11文件属性中加密内容以保护数据  如何在 Go 中正确反序列化 XML 多节点数组(解决仅解析首个元素的问题)  GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?  LINUX如何删除用户和用户组_Linux userdel和groupdel命令用法【系统管理】  零基础学会Python自动化办公_高效处理Excel与PDF文档  Python多线程使用规范_线程安全解析【教程】  PHP的FastAdmin架构适合二次开发吗_特点分析【介绍】  Win10怎么卸载迅雷_Win10彻底卸载迅雷方法【步骤】  如何在Golang中验证模块完整性_Golanggo.sum校验与安全实践  如何用正则表达式精确匹配“start”到“end”之间最多含一个换行符的文本段  Win11怎么连接蓝牙耳机_Win11蓝牙设备配对与连接教程【步骤】  如何使用 Selenium 正确获取篮球参考网站球员名单元素列表  Windows10如何更改开机密码_Win10登录选项更改密码教程  Mac系统更新下载慢或失败怎么办_解决macOS升级问题【方法】 

 2025-12-22

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.