在严格模式下,修改已冻结、密封或不可扩展对象的原型会抛出typeerror,这是主动保护机制;object.isfrozen、object.issealed、object.isextensible可检测原型是否被锁定,正确做法是在创建初期用object.create指定原型,避免后期修改。
在严格模式下,尝试修改不可配置的原型属性(比如用 object.setprototypeof 更换已冻结对象的原型)会直接抛出 typeerror,导致运行时崩溃。这不是“bug”,而是严格模式的主动保护机制——它把原本静默失败的操作变成可捕获、可修复的错误。
确认对象是否已被冻结或不可扩展
原型被锁定,往往是因为对象本身已被冻结(Object.freeze)、密封(Object.seal)或设为不可扩展(Object.preventExtensions)。这些操作都会禁用原型修改:
-
Object.isFrozen(obj)→ 返回 true 表示无法修改原型 -
Object.isSealed(obj)→ 同样禁止修改原型(比冻结宽松,但原型仍受保护) -
Object.isExtensible(obj)→ 若返回 false,则setPrototypeOf必然失败
避免在运行时强行替换原型
一旦对象进入不可扩展状态,任何 Object.setPrototypeOf(obj, newProto) 都会失败。正确做法是:在对象创建初期就设定好原型,之后不再变更:
- 用
Object.create(proto)初始化对象,并传入期望的原型 - 若需动态继承,改用组合模式:把行为封装成普通方法或工具函数,而非依赖原型链切换
- 不要对第三方库返回的对象(如 React 组件实例、DOM 元素)调用
setPrototypeOf—— 它们通常已被引擎内部锁定
捕获并降级处理(仅限调试或兜底)
如果确实需要兼容性试探(例如 polyfill 检测环境能力),可用 try/catch 捕获错误,但不建议用于主逻辑:
```js
"use strict";
const obj = {};
Object.freeze(obj);
try {
Object.setPrototypeOf(obj, { foo: "bar" });
} catch (e) {
// e instanceof TypeError,且 message 通常含 "prototype"
console.warn("原型不可修改,跳过设置");
// 此处可 fallback 到属性拷贝、代理封装等替代方案
}
检查是否误启用了严格模式
有时崩溃并非来自代码本意,而是模块自动启用严格模式(所有 ES 模块默认严格)。如果你在非模块环境中混用了 import 或构建工具(如 Vite/Webpack),可能意外触发了严格约束。验证方式:
- 查看报错堆栈中是否包含
.mjs、import或打包后的__webpack_require__调用 - 临时在出问题的文件顶部加
console.log(this === undefined);—— 严格模式下顶层函数中输出 true - 若确认是模块环境引起,就接受该约束,转而重构设计,而非绕过严格模式











