最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
JavaScript 中如何实现支持描述符保留的深拷贝方法
时间:2026-07-07 11:25:52 编辑:袖梨 来源:一聚教程网
JavaScript中实现支持描述符保留的深拷贝,关键在于用Object.getOwnPropertyDescriptors获取所有自有属性描述符,递归深拷贝value/get/set,再用Object.defineProperties重建;需处理循环引用、访问器this指向、Symbol键、不可枚举属性及Date/RegExp/Map/Set等特殊对象。
JavaScript 中实现支持描述符保留的深拷贝,关键在于不能只复制属性值,还要完整还原 Object.defineProperty 所定义的所有特性(如 enumerable、writable、configurable、get/set)。JSON 序列化、structuredClone 或简单递归赋值都无法保留这些元信息。
使用 Object.getOwnPropertyDescriptors + 递归重建
这是最直接可控的方式:先用 Object.getOwnPropertyDescriptors 获取源对象所有自有属性的完整描述符,再对每个描述符中的 value 或 get/set 函数做深拷贝,最后用 Object.defineProperties 在新对象上重建。
- 对普通值(基本类型、null、undefined)直接返回
- 对函数,通常不深拷贝(函数无法真正“复制”,且闭包不可序列化),可选择原样保留或浅拷贝引用
- 对对象/数组,递归处理其自身属性描述符;注意避免循环引用,需用 WeakMap 记录已拷贝对象
- 对
get/set,需重新包装——内部访问的this要指向新对象,因此不能直接赋值,要重写访问器逻辑
处理访问器属性(getter/setter)的细节
直接复制 get 函数会导致它内部的 this 仍指向原对象。正确做法是:在新对象上定义新的访问器,让 get 从新对象读取对应键(若目标是普通值),或调用深拷贝后的 getter 函数(若 getter 本身依赖其他状态)。
- 若原属性是
{ get() { return this._x * 2; } },拷贝后应生成{ get() { return this._x * 2; } },其中this._x是新对象上的深拷贝值 - 更稳妥的做法是:对访问器属性,仅拷贝其函数体(通过
toString()),并在新上下文中执行——但这有局限(无法处理闭包变量);生产环境建议明确约定访问器不依赖外部闭包
兼容 Symbol 键与不可枚举属性
Object.getOwnPropertyDescriptors 天然支持 Symbol 类型的键和不可枚举属性,无需额外处理。但要注意:for...in 和 Object.keys 会忽略它们,必须坚持使用该 API 才能保全。
立即学习“Java免费学习笔记(深入)”;
- 确保递归时对每个对象都调用
Object.getOwnPropertyDescriptors(obj),而不是Object.keys(obj) - Symbol 键的 descriptor 会被正常捕获,拷贝后仍为 Symbol 键,语义完全一致
- 不可枚举属性(
enumerable: false)在拷贝后也保持不可枚举,不影响遍历行为
避开内置类与特殊对象的陷阱
Date、RegExp、Map、Set、ArrayBuffer 等类型需单独判断并实例化。它们的描述符可能包含内部槽(internal slots),无法通过 getOwnPropertyDescriptors 完全暴露。例如:
-
new Date()的[[DateValue]]不可枚举也不可配置,但可通过getTime()提取后重建 -
RegExp实例的source和flags可读,用new RegExp(desc.source, desc.flags)构造 -
Map/Set需遍历entries()或values(),对键值对分别深拷贝后再填入新实例
不复杂但容易忽略:深拷贝描述符的本质不是“复制数据”,而是“复现定义行为”。只要每一步都基于 defineProperty 级别的控制,并小心处理函数、循环引用和宿主对象,就能可靠保留所有元信息。
相关文章
- 《红色沙漠》抓娃娃机游玩位置分享 07-08
- 境界刀鸣天锁斩月触发方法是什么 07-08
- REPLACED第二章全部收集品位置一览 07-08
- 最强麒麟芯+自研风冷 华为Mate80 Pro MAX 风驰版全面评测:涡轮散热封神 性能稳到骨子里 07-08
- 燕云十六声天下常平成就攻略 07-08
- 风启之旅育苗床制作方法介绍说明 07-08