Proxy 可通过拦截 set 和 deleteProperty 操作实现只读控制:set 拦截赋值并拒绝修改,deleteProperty 拦截属性删除;配合 get 可实现深层只读或提示,封装为工具函数支持白名单与冻结协同,但仅代理一层且不阻止反射操作。

Proxy 可以拦截对象的读写操作,从而实现只读属性控制——关键在于拦截 set 和 deleteProperty 操作,并对非法修改抛出错误。
拦截赋值操作(set)
通过 Proxy 的 set 拦截器,可以阻止对目标对象属性的任何写入。只要返回 false 或抛出错误,就能让赋值失败(严格模式下必须抛错,否则静默失败)。
- 在
set中检查是否允许修改:例如根据属性名白名单、或统一禁止所有写入 - 注意:仅拦截到
obj.prop = value这类直接赋值,不覆盖Object.defineProperty等底层操作 - 示例:统一拒绝所有写入,除非明确标记为可写
拦截属性删除(deleteProperty)
只读对象通常也不应允许删除已有属性。用 deleteProperty 拦截器可阻止 delete obj.key 操作。
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 返回
false表示删除失败;在严格模式下会抛出TypeError - 若需部分属性可删,可在拦截器中加判断逻辑(如跳过特定属性名)
- 注意:该拦截对
Reflect.deleteProperty同样生效
配合 get 实现“伪只读”提示(可选)
get 拦截器本身不改变只读性,但可用于增强体验:比如对被冻结的属性返回特殊提示,或记录访问日志。
- 不推荐在
get中抛错(影响正常读取),但可返回包装后的只读代理值 - 若需深层只读(嵌套对象也只读),需在
get中对返回的 object 再次用 Proxy 包裹 - 简单场景下,
get可用于区分原始值与代理值,便于调试
实际封装一个只读代理工具
把上述逻辑封装成复用函数,支持传入白名单或完全冻结:
- 接受目标对象和可选配置(如
allowWrite: ['id']) - 内部使用
set和deleteProperty拦截,按规则放行或拒绝 - 建议搭配
Object.freeze使用:先冻结基础结构,再用 Proxy 控制运行时行为 - 注意:Proxy 只代理一层,深层嵌套需递归代理或结合
get动态包装
不复杂但容易忽略:Proxy 创建的是新对象,原对象不受影响;只读是运行时保护,无法阻止反射类操作(如 Reflect.set 配合非严格模式),但对绝大多数业务场景已足够可靠。

















