Reflect 本身不能直接实现属性的动态转移,需结合 getOwnPropertyDescriptor、defineProperty 和 deleteProperty 等方法协同完成:先用 Reflect.getOwnPropertyDescriptor 获取源属性完整描述符,再用 Reflect.defineProperty 将其定义到目标对象,最后用 Reflect.deleteProperty 安全删除源属性。

使用 Reflect 本身无法直接“实现属性的动态转移”,因为 Reflect 是一组静态操作方法的集合(如 get、set、ownKeys 等),它不提供属性迁移或重绑定逻辑。所谓“属性的动态转移”,通常指在运行时将一个对象的某些属性“移动”到另一个对象上(包括值、描述符、可枚举性、getter/setter 等),并可能删除原属性。这需要结合 Reflect 与 Object.getOwnPropertyDescriptor、Object.defineProperty、delete 等协同完成。
获取源属性的完整描述符
要准确转移属性(尤其是访问器属性或不可枚举属性),不能只复制值,而应获取其完整属性描述符。Reflect 提供了 Reflect.getOwnPropertyDescriptor,它是 Object.getOwnPropertyDescriptor 的 Reflect 版本,语义一致且更适配 Proxy 场景:
- 用
Reflect.getOwnPropertyDescriptor(source, key)获取属性配置(value/writable/enumerable/configurable/get/set) - 若返回
undefined,说明该属性不存在或为继承属性(需配合Reflect.ownKeys或Object.getOwnPropertyNames过滤) - 注意:它不会获取原型链上的属性,仅 own property
在目标对象上定义同配置属性
拿到描述符后,用 Reflect.defineProperty 将其应用到目标对象。相比 Object.defineProperty,它返回布尔值(成功 true / 失败 false),便于错误处理:
const success = Reflect.defineProperty(target, key, descriptor)- 若
success为false,可能是目标对象不可扩展、descriptor 冲突(如 configurable: false 但尝试重复定义)等 - 对访问器属性(含 get/set),必须同时传入完整的
get和set字段,不能只设其一
安全删除源属性(可选)
若需“转移”(即移除源属性),使用 Reflect.deleteProperty —— 它是 delete obj.key 的函数式、可代理化替代:
const deleted = Reflect.deleteProperty(source, key)- 返回
true表示删除成功(或属性本就不存在);false表示失败(如属性不可配置) - 比
delete操作符更可控,尤其在 Proxy 中能被deletePropertytrap 捕获
封装一个安全的 transferProperty 工具函数
把上述步骤组合起来,可写出通用转移逻辑:
function transferProperty(source, target, key) {
const desc = Reflect.getOwnPropertyDescriptor(source, key);
if (!desc) return false;
const defined = Reflect.defineProperty(target, key, desc);
if (!defined) return false;
return Reflect.deleteProperty(source, key);
}
调用如:transferProperty(objA, objB, 'name')。它会尝试把 objA.name 的完整定义迁移到 objB,并从 objA 删除。注意:不可配置的属性无法被 delete,此时函数返回 false,需额外判断处理。


















