JavaScript深拷贝如何正确克隆自定义类实例对象
时间:2026-08-12 | 作者:星河游者 | 阅读:0自定义类实例做深拷贝,不能按普通对象那套思路直接照搬。构造逻辑和私有状态都得手动处理清楚。原因很简单:这类实例里往往不只有数据本身,还带着原型、方法、不可枚举属性,以及 Symbol 字段。
更稳妥的处理方式是这样一套流程:先拿到原始原型,再通过 Object.create 创建新实例;接着用 Object.getOwnPropertyDescriptors 取出全部自有属性描述符;然后对其中的 value 做递归深拷贝;最后通过 Object.defineProperties 重新定义回去,并结合 WeakMap 处理循环引用问题。
深拷贝自定义类实例不能靠通用递归或 JSON 方法。必须显式处理构造逻辑和私有状态。因为类实例不是普通对象,它有原型、方法、不可枚举属性,甚至可能含闭包或 Symbol 私有字段。
处理自定义类实例深拷贝的核心思路
- 先保留原对象的原型链
- 再完整复制自有属性
- 特殊私有状态单独处理
- 最后用
WeakMap解决循环引用
识别并保留构造器与原型链
直接用 Object.assign 或朴素递归,会丢掉原型和方法。正确做法是:先用 Object.getPrototypeOf(obj) 获取原实例原型,再用 Object.create(proto) 创建新对象,确保继承关系 intact。
- 避免用
new obj.constructor()—— 构造函数可能依赖参数、副作用或 this 绑定,盲目调用易出错 - 优先走「原型继承 + 属性赋值」路径:创建空实例 → 复制自有可枚举/不可枚举属性(包括 Symbol 键)→ 不触发 constructor
- 若类明确支持克隆(如提供
clone()方法),应优先调用该方法而非自行重建
手动复制自有属性(含 Symbol 和不可枚举项)
类实例的字段可能藏在 Symbol 键、Object.getOwnPropertyNames() 或 Object.getOwnPropertySymbols() 中。仅靠 for...in 会漏掉。
- 用
Object.getOwnPropertyDescriptors(obj)获取所有自有属性描述符(含 get/set、writable、enumerable、configurable) - 对每个 descriptor 递归深拷贝 value(注意:getter/setter 函数不拷贝,只保留原引用或跳过)
- 用
Object.defineProperties(newObj, descriptors)批量定义,保持属性特性(如只读、不可配置)
特殊字段需按类约定单独处理
很多类内部维护非公开状态,如缓存、事件监听器、私有字段 #field。这些无法通过反射访问,必须由类自身暴露接口,或由开发者约定规则。
- ES2024 私有字段(
#name)完全不可反射,只能靠类提供toJSON()、serialize()或clone()方法导出可拷贝数据 - 若类有静态
from()或deserialize()方法,可用其配合序列化数据重建实例 - 第三方库如 Lodash 的
cloneDeepWith允许传入 customizer 函数,在遇到特定构造器时返回定制克隆结果
循环引用与缓存机制不能省
类实例之间常存在引用闭环,如父子关系、观察者列表。不加缓存,会导致栈溢出或无限递归。
- 始终用
WeakMap缓存源对象 → 克隆对象映射,首次克隆时新建,重复出现时直接返回已有结果 - 缓存应在进入克隆前检查,而不是等属性遍历完才判断——否则已递归进去了
- 注意 WeakMap 键必须是对象,基本类型或 null/undefined 不参与缓存逻辑
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- JavaScript正则表达式批量处理HTML标签转义与替换方法
- 时间:2026-08-21
-
- JavaScript函数默认参数的精准JSDoc类型注解方法
- 时间:2026-08-21
-
- JavaScript设置Cookie的SameSite属性防范CSRF攻击
- 时间:2026-08-21
-
- JavaScript中BOM如何打开新的浏览器窗口标签
- 时间:2026-08-20
-
- JavaScript微任务队列在事件循环中的执行机制
- 时间:2026-08-20
-
- JavaScript中网络超时如何用流程控制实现中断
- 时间:2026-08-20
-
- JavaScript防抖函数原理与减少高频事件触发方法
- 时间:2026-08-20
-
- TypeScript六个颠覆认知的核心知识点解析
- 时间:2026-08-20
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
