要让对象结构真正“锁死”,必须同时配合使用isextensible和preventextensions:preventextensions执行真实锁定(需调用reflect.preventextensions(target)),isextensible则必须如实反映target状态(推荐reflect.isextensible(target)),二者逻辑不一致会直接报错。

要让对象结构真正“锁死”,isExtensible 和 preventExtensions 必须配合使用,不能只拦一个。单独拦截 preventExtensions 不生效,单独返回 isExtensible 为 false 也不合法——JS 引擎会校验二者逻辑一致,否则直接报错。
preventExtensions 是“上锁动作”,必须真实改变目标状态
这个 trap 拦的是 Object.preventExtensions(proxy) 调用。它不是“声明不可扩展”,而是“执行不可扩展”。关键点是:
- 必须调用
Reflect.preventExtensions(target)才能让 target 真正变为不可扩展 - 之后
Object.isExtensible(target)才会返回false,满足后续校验 - trap 返回
true前,target 必须已不可扩展;否则抛错:“trap returned truish but the proxy target is extensible” - 返回
false表示拒绝该操作,proxy 仍保持可扩展
isExtensible 是“状态快照”,必须与实际一致
这个 trap 拦的是 Object.isExtensible(proxy) 查询。它的作用是对外暴露当前是否可扩展,但不能凭空返回 false:
- 必须基于 target 的真实状态返回,推荐直接用
Reflect.isExtensible(target) - 如果 preventExtensions 已成功执行,
Reflect.isExtensible(target)自动为false,isExtensible trap 返回false就自然成立 - 若手动硬写
return false,但 target 实际仍可扩展,就会破坏一致性,某些引擎或严格模式下可能出问题
联动的关键:一次 preventExtensions 触发后,isExtensible 自动跟随
二者不是独立开关,而是一体两面。典型正确写法:
- 在
preventExtensions中先调用Reflect.preventExtensions(target),再返回其结果 - 在
isExtensible中直接返回Reflect.isExtensible(target) - 这样只要有人调用
Object.preventExtensions(proxy),target 就真实锁定,后续所有Object.isExtensible(proxy)都返回false,新增属性(如proxy.newProp = 1)在严格模式下直接报错
加一层控制:只允许特定时机锁死
你可以在 preventExtensions 里加入业务判断,比如仅生产环境才允许锁死:
- 开发时返回
false并警告,阻止误操作 - 生产时调用
Reflect.preventExtensions(target)并返回结果 - isExtensible 保持被动同步,不做额外干预
- 日志记录每次锁死尝试,便于追踪结构变更点











