核心是提前拦截递归,用weakmap缓存“旧对象→新对象”映射以避免重复拷贝和内存泄漏;按类型分流处理,缓存实例需显式传递;现代环境优先使用structuredclone。

核心是提前拦截,而不是等递归走到死胡同再刹车。关键在于每次准备拷贝一个对象前,先查它是否已被处理过;如果已存在副本,直接返回,跳过后续递归。
用 WeakMap 缓存“旧对象 → 新对象”映射
WeakMap 是最合适的缓存容器,因为:
- 键必须是对象,天然适配引用类型判断
- 弱引用特性,不阻止垃圾回收,避免内存泄漏
- 不会暴露内部数据,安全性好
每次进入拷贝逻辑时,先用原对象作 key 查询 WeakMap:
- 查到了 → 直接返回对应的新对象
- 没查到 → 先创建空对象({} 或 []),立刻存入 WeakMap,再继续遍历属性
分类型处理,避免误入递归陷阱
不是所有值都要进缓存或递归。需按类型明确分流:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- null、基本类型(string/number/boolean/symbol/bigint/undefined)→ 直接返回,不缓存
- Date、RegExp、ArrayBuffer、TypedArray → 用构造函数新建实例(如 new Date(obj)),并存入 WeakMap 防重复
- Map / Set → 新建实例后,递归拷贝其键和值(键也可能是对象,同样走 WeakMap 检查)
- 普通对象或数组 → 先占位再赋值,确保循环中能命中缓存
缓存实例必须显式传递,不能默认初始化
常见错误写法:function deepClone(obj, cache = {}),会导致多次调用共用一个 cache,跨作用域污染。
正确做法:
- 参数默认设为
cache = null - 首次调用时判断:
if (cache == null) cache = new WeakMap() - 所有递归调用都显式传入当前
cache实例
优先使用 structuredClone(现代环境)
Chrome 98+、Node.js 17.0+ 已支持 structuredClone(obj):
- 一行代码解决,内置循环检测
- 原生支持 Date、Map、Set、Blob、TypedArray 等特殊对象
- 语义准确、性能稳定,无需手动维护缓存逻辑
仅当需要兼容老环境或定制行为(如保留 Symbol、控制属性描述符)时,才手写实现。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










