Proxy.revocable() 提供单向撤销访问权限而非销毁,调用 revoke() 后代理立即失效并抛出 TypeError;必须及时调用 revoke 以确保安全,尤其在临时敏感代理、沙箱退出、资源生命周期绑定等场景。

ES6 的 Proxy.revocable() 提供的不是“销毁”,而是**单向撤销访问权限**——调用 revoke() 后,代理对象立即失效,任何后续操作都会抛出 TypeError: Cannot perform 'xxx' on a revoked proxy。它不清理内存、不解除引用、也不影响原始目标对象,所以“安全销毁”的核心在于:**确保 revoke 被及时调用 + 避免 proxy 泄漏 + 不依赖其后续行为**。
何时必须调用 revoke 才算“安全”
撤销不是可选优化,而是必要清理步骤,尤其在以下场景:
- 临时敏感代理:比如封装了 token 或密钥的配置对象,一旦使用完成就应立即撤销,防止被意外复用或调试时误读
- 沙箱环境退出:在动态执行第三方脚本的沙箱中,脚本执行完毕后必须 revoke 对应 proxy,否则可能持续持有对内部状态的访问通道
- 资源生命周期绑定:如代理一个 WebSocket 连接对象,连接关闭时同步 revoke,避免 proxy 在连接已断后仍被调用引发不可预期错误
如何避免 revoke 后的常见陷阱
撤销不可逆,且异常明确。但开发者容易忽略两点:
-
revoke 是幂等的:多次调用不会报错,也不会重复生效,可以放心加 guard 判断(如
if (revoke) revoke()),适合放在finally或清理函数中 -
proxy 引用仍存在,但已失效:撤销后变量
proxy本身不变成null或undefined,只是所有操作都失败。务必避免在 revoke 后还把它传给其他函数或存入全局缓存 -
无法通过 try/catch 拦截所有撤销后访问:例如
typeof proxy、proxy === null等非拦截操作仍可执行;只有触发 handler 陷阱的操作(get、set、apply等)才会抛错。所以不能靠“捕获异常”来判断是否已撤销
推荐的安全实践模式
把 revoke 和 proxy 绑定管理,减少裸露引用:
- 用立即执行函数或模块作用域封装,让
proxy和revoke不暴露到外部作用域 - 返回一个带
destroy()方法的对象,内部调用revoke并将自身引用置为null(辅助 GC) - 结合
WeakRef或FinalizationRegistry做兜底(仅限高级场景):注册 proxy 对象,当它被垃圾回收时触发日志或告警,帮助发现未显式 revoke 的遗漏
撤销后目标对象完全不受影响
revoke() 只切断 proxy 与 handler 的联系,目标对象(target)本身毫发无损,所有属性、方法、引用关系照常工作。你仍然可以自由操作 target,也可以用它创建新的 proxy。撤销不是“销毁 target”,而是“作废这个中间门禁卡”。


















