Reflect.ownKeys配合Reflect.getOwnPropertyDescriptor能完整获取所有自有属性描述符,覆盖不可枚举属性、Symbol键及getter/setter;而Object.keys和for...in会遗漏这些情况。

在手写深拷贝时,用 Reflect.getOwnPropertyDescriptor 配合 Reflect.ownKeys 是比 Object.keys + for...in 更安全、更完整的方式获取自有属性描述符,尤其能覆盖不可枚举、Symbol 键、getter/setter 等边界情况。
为什么不用 Object.keys 或 for...in?
Object.keys 只返回可枚举的自有字符串键;for...in 还会遍历原型链上的可枚举属性。两者都漏掉:
- 不可枚举属性(如 Object.defineProperty(obj, 'x', { value: 1, enumerable: false }))
- Symbol 类型的自有属性(如 obj[Symbol('id')] = 42)
- getter/setter 描述符本身(仅靠 obj[key] 读值会触发 getter,且无法还原 setter)
用 Reflect.ownKeys + Reflect.getOwnPropertyDescriptor 安全提取
Reflect.ownKeys(target) 返回所有自有键(含字符串和 Symbol),再对每个键调用 Reflect.getOwnPropertyDescriptor(target, key),就能拿到完整的属性描述符对象(包括 value、get、set、enumerable、configurable、writable)。
- 不依赖属性是否可枚举,不访问原型链
- 能区分数据属性(
value)和访问器属性(get/set),拷贝时可分别处理 - 保留
configurable和writable等元信息,有利于还原原始定义行为
实际深拷贝中如何使用(简化示意)
伪代码逻辑如下:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
<p>const target = Array.isArray(obj) ? [] : {};
const keys = Reflect.ownKeys(obj);</p><p>for (const key of keys) {
const desc = Reflect.getOwnPropertyDescriptor(obj, key);
if (!desc) continue; // 理论上不会发生,但防御性检查</p><pre class="brush:php;toolbar:false;">// 深拷贝 value 或 get/set 函数体(注意:函数通常浅拷贝,除非明确要复制闭包)
if ('value' in desc) {
desc.value = deepClone(desc.value);
} else if ('get' in desc || 'set' in desc) {
// getter/setter 一般不递归深拷贝函数体,直接复用(函数是不可变的)
// 若需隔离作用域,需额外处理(如重写为新函数),但非常规需求
}
// 用 Object.defineProperty 重建属性(保留所有 descriptor 字段)
Object.defineProperty(target, key, desc);}
return target; }
注意事项和限制
Reflect.getOwnPropertyDescriptor 对于某些内置对象(如 Date、RegExp、Map、Set)可能返回 undefined 或不完整描述符,因为它们内部状态不完全暴露在属性系统中。此时应优先识别类型,走专用克隆路径(如 new Date(obj)、new RegExp(obj)、new Map(obj) 等)。
- 不能拷贝不可配置(
configurable: false)又不可写(writable: false)的属性?可以——只要目标对象允许定义即可(新建对象默认允许) - 不能还原
[[Prototype]]?可以,拷贝后用Object.setPrototypeOf(target, Object.getPrototypeOf(obj))补上 - 循环引用仍需单独用 WeakMap 缓存处理,
Reflect不解决该问题
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










