新闻中心
在J*aScript中,如何实现真正意义上的深拷贝以处理循环引用?
答案:J*aScript中实现深拷贝需处理类型差异和循环引用,使用WeakMap避免无限递归。支持Date、RegExp、原型链及循环引用,如a.self=a可正确克隆,确保b.self===b,完整方案优于JSON方法。

在J*aScript中实现真正意义上的深拷贝,尤其是处理循环引用,不能依赖简单的JSON.parse(JSON.stringify())方法,因为它无法处理函数、undefined、Symbol、日期、正则等类型,更无法识别循环引用,会导致报错。
要正确实现支持循环引用的深拷贝,核心思路是:使用WeakMap记录已拷贝的对象,避免无限递归。下面是一个完整且实用的实现方案。
1. 检测数据类型并分类处理
深拷贝需要根据不同的数据类型采取不同的复制策略:
- 基础类型(string、number、boolean、null、undefined、symbol、bigint)直接返回
- 不可遍历对象如Date、RegExp、Error、Function 直接构造或原样返回
- 可遍历对象(普通对象、数组)递归复制属性
2. 使用WeakMap追踪已访问对象
当遇到对象时,先检查是否已在WeakMap中存在对应的拷贝,若存在则直接返回,防止循环引用导致栈溢出。
立即学习“J*a免费学习笔记(深入)”;
ChatCut
AI视频剪辑工具
1086
查看详情
WeakMap适合这里,因为它的键是弱引用,不会影响垃圾回收。
3. 完整实现代码
function deepClone(obj, hash = new WeakMap(
)) {if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 处理包装对象
if (obj instanceof Boolean) return new Boolean(obj);
if (obj instanceof Number) return new Number(obj);
if (obj instanceof String) return new String(obj);
// 如果已拷贝过,直接返回缓存结果
if (hash.has(obj)) return hash.get(obj);
// 初始化目标对象,保持原构造函数
const clone = Array.isArray(obj)
? []
: Object.create(Object.getPrototypeOf(obj));
// 记录当前对象已被拷贝
hash.set(obj, clone);
// 递归拷贝所有可枚举属性
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], hash);
}
}
return clone;
}
4. 验证循环引用处理能力
测试用例如下:
const a = { name: 'John' };a.self = a; // 循环引用
const b = deepClone(a);
console.log(b.self === b); // true,结构正确
这个版本能正确保留原型链、处理数组、普通对象,并安全应对循环引用。
基本上就这些。不复杂但容易忽略细节,比如原型继承和内置对象的特殊处理。实际项目中也可考虑使用Lodash的_.cloneDeep,其内部实现更完善,但理解原理有助于排查边界问题。
以上就是在J*aScript中,如何实现真正意义上的深拷贝以处理循环引用?的详细内容,更多请关注其它相关文章!
# 如何使用
# 南极人营销推广方案
# 音乐推广的网站
# 千户苗寨营销推广方案
# 企业seo培训顾问
# 服务行业营销推广推荐
# 网站砍入推广代码
# 张家界商城seo
# 绥化seo服务平台
# 东平优化seo
# 黄陂整合营销推广
# 它很
# 是一个
# javascript
# 管理器
# 有何
# 意义上
# 遍历
# 如何实现
# 有什么
# 递归
# 栈
# json
# js
# java
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
微信网页版登录教程_微信网页版登录入口在哪
俄罗斯浏览器官网直达链接 俄罗斯浏览器最新在线入口导航
腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程
如何创建没有密码的Windows本地账户_跳过微软账户登录的技巧【教程】
Lar*el的路由模型绑定怎么用_Lar*el Route Model Binding简化控制器逻辑
冬*霸灯泡不亮怎么办_浴霸取暖灯一盏不亮的灯座清洁修复法
如何更改在 Excel 中打开超链接时的默认浏览器
照顾宝贝2小游戏免费秒玩入口
python3时间如何用calendar输出?
126邮箱账号注册 电脑版登录入口
css滚动区域卡顿如何改善_css滚动问题用will-change优化渲染
美团外卖商家服务中心入口 美团商家版官网入口
qq邮箱发邮件给国外发不出去_QQ邮箱国际邮件发送失败原因与解决
mc.js官网登录入口 mc.js官方登录入口最新版
windows10怎么关闭系统提示音_windows10彻底静音设置方法
windows10怎么查看硬盘序列号_windows10硬盘id查询命令
Tabulator表格中精确实现日期时间排序的指南
使用 Pandas 高效处理 .dat 文件:字符清理与数据计算
圆通快递查询实时追踪 圆通物流包裹状态快速查看
Go语言中JSON数据解码与字段访问指南
J*aScriptWebpack优化_J*aScript构建工具实战
Promise错误处理:在catch后终止链式then执行的策略
魅族20怎样在浏览器开无图省流_iPhone魅族20浏览器开无图省流【流量节省】
J*aScript Promise链中如何正确终止后续.then执行并处理错误
cad怎么合并重叠的线段_cad清理重复重叠线条的操作方法
菜鸟取件码是什么怎么查 最全查询渠道汇总
12306选座怎么选到临时改签座_12306改签选座策略与步骤
GemBox Document HTML转PDF垂直文本渲染问题及解决方案
Go语言中的*string:深入理解字符串指针
BetterDiscord插件中安全更新用户简介的实践指南
解决 MongoDB 聚合查询中对象数组 _id 匹配问题
荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】
12306选座怎么选到特殊座位_12306特殊座位选择注意事项
使用J*aScript检测输入元素是否包含在特定类中
html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】
DLsite中文平台入口 DLsite官网内容在线查看
如何使用纯J*aScript判断Input元素是否在特定类容器内
Windows7怎么硬盘安装 Windows7提取ISO镜像到非系统盘并运行setup.exe实现硬盘直装【教程】
整合Supabase认证与Django模型:跨模式迁移的解决方案
Win11怎么开启卓越性能模式 Win11电源选项启用高性能释放硬件潜力【方法】
反效果?《战地6》免费试玩开启后玩家数不升反降
JUnit5/Mockito:优雅测试内部依赖与异常处理的实践
在python-socketio事件处理器中安全访问Flask应用上下文
AO3中文官网链接_AO3网页版稳定镜像站
动漫岛观看全网网 动漫岛在线正版动漫入口
解决Rails应用中内容错位与Turbo警告:meta标签误用导致富文本渲染异常
抖音未来赚钱的新趋势 2025年值得关注的变现风口分析
J*aScript中如何高效提取对象指定属性
快手赚钱渠道_快手收益来源
谷歌浏览器最新官方入口链接 谷歌浏览器网页版官网导航


2025-10-06
浏览次数:次
返回列表