Proxy 通过 defineProperty 捕获器拦截属性描述符设置,接收 target、prop、descriptor 三参数,须显式返回 true 才表示接受操作;返回 false 会阻止定义,真正设置需调用 Reflect.defineProperty;它仅响应 Object.defineProperty() 等显式调用,不拦截普通赋值(由 set trap 处理),且与 set trap 分别针对元信息设定和值写入。

Proxy 可以拦截对象属性描述符的设置,关键在于使用 defineProperty 捕获器(trap),它会在调用 Object.defineProperty()、Object.defineProperties() 或某些内部操作(如 class 字段初始化)时触发。
defineProperty 捕获器的基本用法
该 trap 接收三个参数:目标对象(target)、属性名(property)、以及待设置的属性描述符(descriptor)。必须显式返回 true 才表示定义成功;返回 false 或抛出错误会阻止定义。
- 返回
true表示接受本次定义操作(但不自动执行,需手动调用Reflect.defineProperty()或类似逻辑) - 返回
false会导致Object.defineProperty()抛出TypeError(严格模式下)或静默失败(非严格模式) - 若想真正设置属性,通常需配合
Reflect.defineProperty(target, property, descriptor)
拦截并修改描述符内容
你可以在 defineProperty 中检查、过滤或改写传入的 descriptor,例如禁止配置 writable: false、强制添加 enumerable: true,或记录所有定义行为。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
例如,限制只允许定义可枚举、可配置的属性:
const handler = {
defineProperty(target, prop, descriptor) {
if (descriptor.enumerable !== true || descriptor.configurable !== true) {
console.warn(`拒绝定义 ${prop}:要求 enumerable 和 configurable 均为 true`);
return false;
}
return Reflect.defineProperty(target, prop, descriptor);
}
};
注意不可代理的内置行为
并非所有属性定义都会触发 defineProperty trap:
- 普通赋值语句(
obj.x = 1)走的是settrap,不是defineProperty - 使用
Object.defineProperty()显式调用才会进入该 trap - 某些内置对象(如
Array.prototype)或冻结对象(Object.freeze())上定义属性可能被直接拒绝,trap 不会执行 - Proxy 自身不能拦截对
length等数组特有属性的 defineProperty(除非目标是普通对象)
与 set trap 的区别
set 拦截的是「赋值」(即 obj.prop = value),关注的是值写入;而 defineProperty 拦截的是「属性元信息设定」,包括 value、writable、enumerable、configurable、get、set 等完整描述符。两者互不替代,需按需同时使用。

















