javascript高性能深拷贝需用weakmap缓存已拷贝对象以解决循环引用,按类型分路径处理(array.isarray、instanceof等)减少判断开销,预分配数组长度、手动遍历属性提升性能,避免json方案缺陷,并可选支持自定义逻辑与原型保留。

JavaScript 中实现支持循环引用的高性能深拷贝,核心在于用 WeakMap 记录已拷贝的对象引用,避免重复遍历和无限递归,同时尽量减少属性访问与类型判断开销。不依赖 JSON(无法处理函数、undefined、Date、RegExp 等),也不用递归爆栈或频繁创建中间对象。
用 WeakMap 缓存已拷贝对象,解决循环引用
WeakMap 是理想选择:键是原对象(引用类型),值是对应的新对象,且不影响垃圾回收。每次进入对象/数组时先查缓存,命中则直接返回,跳过后续克隆逻辑。
- WeakMap 的 key 必须是对象,天然适配引用类型,原始值(string/number/boolean)无需缓存
- 只对 Object、Array、Date、RegExp、Map、Set 等可循环的类型做缓存;Function、Error、Promise 等通常不循环,可按需决定是否缓存
- 示例逻辑:if (cache.has(obj)) return cache.get(obj);
按类型分路径处理,避免过度通用化
不用一个 typeof + instanceof 堆砌判断,而是优先快速识别常见类型,再逐级降级:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 先用
obj === null和typeof obj !== 'object'拦截原始值和 null - 用
Array.isArray(obj)快速识别数组(比obj.constructor === Array更可靠) - 用
obj instanceof Date、obj instanceof RegExp等明确类型,避免 toString.call 的字符串解析开销 - 普通对象走
Object.keys(obj)或Object.getOwnPropertyDescriptors(obj)(后者保留 getter/setter、不可枚举属性、writable 等)
避免冗余操作,提升关键路径性能
高频拷贝场景下,以下细节影响显著:
- 不用
JSON.parse(JSON.stringify()):丢失函数、NaN、Infinity、undefined、Date 对象变成字符串、正则变空对象、无法处理循环 - 不默认遍历所有 Symbol 属性:除非业务明确需要,否则跳过
Object.getOwnPropertySymbols(),减少迭代次数 - 数组用
new Array(len)预分配长度,再赋值,比[]+push更快 - 对象属性批量赋值用
Object.assign({}, obj)不适用(不深拷、不处理原型、忽略 symbol 和 getter),应手动 for-in 或 keys 循环
可选:支持自定义拷贝逻辑与不可变语义
高性能不等于零配置。可通过传入 options 支持扩展,但保持默认路径无分支:
-
customizer函数:对特定类型(如 moment、axios 实例)提供自定义克隆方式 -
keepPrototype:决定是否用Object.setPrototypeOf(newObj, Object.getPrototypeOf(obj))保留原型链(有性能损耗,按需开启) -
handleUndefined:将 undefined 转为 null 或跳过该属性,避免在 JSON 场景中误用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










