在严格模式下,对不可扩展对象修改__proto__或调用object.setprototypeof会直接抛出typeerror,这是语言设计的主动保护机制;应提前用object.isextensible、issealed或isfrozen判断并避免触发,优先采用object.create、proxy或组合等安全替代方案。

在严格模式下,对不可扩展对象修改 __proto__(或调用 Object.setPrototypeOf)会直接抛出 TypeError,这不是异常情况,而是语言设计的主动保护机制。关键不是“捕获后绕过”,而是提前识别、避免触发,或用更安全的替代方式实现目标。
确认对象是否已被锁定原型
原型修改失败,本质是对象已进入不可扩展状态。可用以下方法快速判断:
-
Object.isExtensible(obj)返回false→setPrototypeOf必然失败 -
Object.isSealed(obj)或Object.isFrozen(obj)返回true→ 同样禁止原型变更(冻结最严格) - 注意:
__proto__是非标准但广泛支持的访问器,其赋值行为与Object.setPrototypeOf一致,同样受上述限制约束
不要在运行时强行替换原型
一旦对象被冻结、密封或设为不可扩展,就应视其结构(包括原型链)为最终态。常见错误场景包括:
- 对第三方库返回的对象(如 React 组件实例、
fetch响应体、DOM 元素)调用setPrototypeOf - 在模块环境(ESM 默认严格模式)中,对初始化后才拿到的对象反复重设原型
- 误将“需要某种行为”理解为“必须挂到原型上”,而忽略了组合或代理等更可控的方式
用创建期设定代替运行时修改
真正稳定的原型关系,应在对象诞生那一刻就确定:
- 用
Object.create(proto)初始化对象,并传入期望的原型对象 - 若需动态行为,封装成普通函数或 class 实例方法,而非依赖切换
[[Prototype]] - 对已有数据对象,可考虑用
Object.assign({}, source, { method() { ... } })或Proxy包装,避免触碰原型链
仅在必要时降级处理(不推荐主逻辑使用)
仅适用于 polyfill 检测、兼容性试探或兜底日志,不可用于核心流程:
- 用
try/catch捕获TypeError,检查错误信息是否含"prototype"或"__proto__" - 失败后转向属性拷贝、装饰器模式、或构造新对象继承所需行为
- 避免静默吞掉错误——至少记录
console.warn,便于后续重构











