reflect本身不提供直接克隆属性描述符的方法,需组合使用reflect.getownpropertydescriptor获取描述符、reflect.defineproperty设置描述符来手动实现;批量克隆需遍历自有属性键并逐个处理,注意value/writable与get/set互斥及configurable/writable约束。

Reflect 本身不提供直接克隆对象属性描述符的方法,它只是提供了一组操作对象属性的静态方法(如 Reflect.getOwnPropertyDescriptor、Reflect.defineProperty 等),你需要配合使用这些方法手动实现“克隆”逻辑。
获取源对象的属性描述符
用 Reflect.getOwnPropertyDescriptor 获取指定属性的完整描述符(包括 value、writable、get、set、enumerable、configurable):
const obj = { a: 1 };
Object.defineProperty(obj, 'b', {
get() { return 2; },
enumerable: false,
configurable: true
});
const desc = Reflect.getOwnPropertyDescriptor(obj, 'b');
// { get: [Function], enumerable: false, configurable: true }
将描述符应用到目标对象
拿到描述符后,用 Reflect.defineProperty 把它设置到新对象上。注意:不能直接赋值,必须用 defineProperty(或 Reflect.defineProperty)才能保留所有元信息:
- 如果描述符含
get/set,目标对象上也要定义访问器属性 - 如果原属性是不可配置/不可写,新属性也需保持一致,否则会失败(严格模式下抛错)
- 对
value和writable的处理要和get/set互斥——不能同时存在
批量克隆所有自有属性描述符
结合 Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols,遍历所有键,逐个获取并定义:
function cloneDescriptors(source, target) {
const keys = [
...Object.getOwnPropertyNames(source),
...Object.getOwnPropertySymbols(source)
];
for (const key of keys) {
const desc = Reflect.getOwnPropertyDescriptor(source, key);
if (desc) {
Reflect.defineProperty(target, key, desc);
}
}
return target;
}
const src = { x: 1 };
Object.defineProperty(src, 'y', { value: 2, writable: false });
const dst = {};
cloneDescriptors(src, dst);
// dst.y 也是不可写的,且与 src.y 描述符完全一致
注意不可枚举和不可配置属性的限制
克隆过程不会自动绕过属性特性约束:
- 若源属性
configurable: false,你无法在目标对象上修改其描述符(除非目标对象本身允许) - 若源属性是继承来的(非自有),
getOwnPropertyDescriptor返回undefined,需用Object.getPrototypeOf配合递归获取,但此时已不属于“克隆自有描述符”范畴 - 某些内置对象(如
Math、Array.prototype)的属性可能不可配置或不可写,尝试克隆可能静默失败或抛错
不复杂但容易忽略:克隆描述符本质是复制元数据,不是深拷贝值;Reflect 只是工具,关键在组合使用 get + define。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











