Lodash 的 cloneDeep 通过类型识别、循环引用防护、位掩码控制和底层复用实现高效深拷贝:区分处理原始值、内置对象、普通对象及不可克隆类型;用 WeakMap 缓存避免栈溢出并保持引用结构;以位掩码组合控制行为,共享 baseClone 核心逻辑;兼顾性能优化如 for 循环遍历、跳过不可枚举属性等。

Lodash 的 cloneDeep 能高效处理复杂对象的深拷贝,核心在于它不是简单递归,而是融合类型识别、循环引用防护、位掩码控制与底层复用的一套成熟机制。它比手写递归更健壮,也比 JSON.parse(JSON.stringify()) 更全面,尤其适合真实项目中嵌套深、含特殊值、存在循环引用的场景。
自动识别并差异化处理各类数据类型
面对不同结构,cloneDeep 不是“一刀切”地递归,而是先判断类型再选择对应策略:
- 原始值(string/number/boolean/null/undefined/Symbol/BigInt):直接返回,不递归
-
Date、RegExp、ArrayBuffer、TypedArray、Map、Set:分别调用对应构造函数创建新实例,保留语义(如
new Date(obj)) -
普通对象或数组:按原型链重建(
Object.create(Object.getPrototypeOf(obj))),确保继承关系不丢失 - 函数、DOM 元素、window 等不可克隆对象:跳过或返回空对象,避免报错
内置 WeakMap 缓存,安全应对循环引用
当对象 A 引用 B,B 又引用 A 时,普通递归会无限展开直至栈溢出。cloneDeep 在内部维护一个 WeakMap 缓存已处理的对象及其副本:
- 每次进入拷贝前,先查缓存;若已存在,直接返回已有副本
- 首次处理时,立即存入缓存,再递归子属性
- WeakMap 的弱引用特性避免内存泄漏,且天然支持对象键
这样既终止了无限递归,又保持了原始对象中的引用结构——新对象里 A 和 B 之间仍维持相同指向关系。
立即学习“Java免费学习笔记(深入)”;
位掩码驱动,逻辑清晰且可扩展
cloneDeep 实际是调用底层 baseClone,通过组合位标志控制行为:
-
CLONE_DEEP_FLAG (1):启用递归遍历 -
CLONE_SYMBOLS_FLAG (4):决定是否拷贝 Symbol 属性 - 两者按位或(
1 | 4 === 5)传入,让同一套基础逻辑支持多种拷贝模式
这种设计使 clone(浅拷贝)、cloneDeep、cloneDeepWith 共享核心,便于维护和优化,也为你自定义拷贝逻辑(如过滤敏感字段)留出接口。
性能优化细节贴近工程实际
它在关键路径做了多项轻量但有效的优化:
- 对数组优先使用
for循环而非forEach,减少函数调用开销 - 跳过不可枚举属性和原型链上的属性,只处理自有可枚举键(
hasOwnProperty+propertyIsEnumerable) - Symbol 属性单独提取处理,避免
for...in遗漏 - 对大型对象,缓存能显著减少重复计算,尤其在含多个相同子结构时


















