递归深拷贝性能优化核心是避免重复、提前终止、按需处理:用weakmap缓存已拷贝对象解决循环引用;仅对array和普通object递归,其余类型快速构造;用getownpropertynames等减少属性枚举开销;批量初始化对象与数组提升赋值效率。

递归实现深拷贝时,性能瓶颈主要来自重复遍历、无限循环引用、冗余类型判断和未缓存的中间结果。优化核心是“避免重复、提前终止、按需处理”。
用 WeakMap 缓存已拷贝对象,解决循环引用并避免重复处理
当对象存在循环引用(如 a.b = a)时,朴素递归会无限深入或栈溢出。WeakMap 可以以原对象为键、拷贝后对象为值,既支持引用相等性判断,又不阻止垃圾回收。
- 每次进入递归前,先查 WeakMap:若已存在对应拷贝,直接返回,中断递归
- 创建新拷贝后,立即存入 WeakMap,确保子属性递归时能命中缓存
- WeakMap 比 Map 更适合——键必须是对象,且不阻碍原对象被回收
只对可变复合类型递归,跳过原始值与不可变对象
字符串、数字、布尔、null、undefined、Symbol、BigInt、Date、RegExp、ArrayBuffer 等无需递归深拷贝;其中 Date、RegExp 等需特殊构造,但不触发嵌套遍历。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 用
typeof+Object.prototype.toString.call()精准识别类型,避免instanceof的跨 iframe 问题 - 对
String、Number等包装对象,直接调用.valueOf()转原始值 - 对
Array和普通Object才真正进入递归分支,其他类型走快速构造路径
扁平化属性访问,减少重复的 Object.keys() 和 for...in
每次递归都调用 Object.keys(obj) 或遍历 for...in,会多次执行属性枚举、排序(ECMAScript 规定 keys 有序)、过滤原型链——开销明显。
- 改用
Object.getOwnPropertyNames()+Object.getPrototypeOf()显式控制是否遍历原型(通常深拷贝不需) - 对数组优先用
length和索引访问,避免 keys() 生成新数组 - 若确定对象无 Symbol 属性,可跳过
Object.getOwnPropertySymbols(),否则按需合并
避免不必要的对象创建与属性赋值
在递归过程中,频繁新建空对象再逐个 obj[key] = value,不如批量初始化更高效。
- 对普通对象,用
Object.assign({}, ...)或Object.create(null)配合defineProperty减少原型链查找 - 对数组,预先用
new Array(len)创建定长数组,再填充,避免动态扩容 - 使用
Object.defineProperty()一次性设置属性(含enumerable、writable等),比默认赋值更可控且略快
递归深拷贝不是越“全”越好,而是越“准”越快——精准识别类型、精准缓存引用、精准控制遍历范围,才能在保证正确性的前提下逼近性能极限。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










