严格模式下object.setprototypeof修改object.freeze对象会立即抛typeerror而非死锁;应避免事后修改,改用object.create初始化、组合代替继承,并冻结关键原型链。

严格模式下用 Object.setPrototypeOf 尝试修改已被 Object.freeze 锁定的对象原型,根本不会造成“死锁”,而是立即抛出 TypeError —— 这是引擎主动终止操作的保护行为,不是卡住或循环等待。所谓“致命死锁”属于误判,真实问题是运行时崩溃,解法核心是**不尝试、不依赖、早规避**。
确认对象是否已被冻结或不可扩展
冻结(Object.freeze)、密封(Object.seal)或禁止扩展(Object.preventExtensions)都会让对象失去修改原型的能力。判断只需一行:
-
Object.isFrozen(obj)→ 返回true表示原型不可改 -
Object.isSealed(obj)→ 同样禁止原型变更 -
Object.isExtensible(obj)→ 若为false,setPrototypeOf必失败
放弃运行时替换原型,改用创建期设定
所有原型链问题,根源在于“事后修补”。正确做法是在对象诞生之初就确定继承关系:
- 用
Object.create(proto)初始化,直接指定原型,避免后期干预 - 需要动态能力时,用组合代替继承:把方法封装成独立函数,通过属性挂载或代理调用
- 不要对第三方返回的对象(如 React 实例、DOM 元素、库内部对象)调用
setPrototypeOf—— 它们往往已被引擎锁定
冻结原生原型以阻断污染入口
如果目标是防止原型链被恶意篡改(比如原型链污染),重点不在单个对象,而在全局基础:
- 在页面最早执行的脚本中冻结关键原型:
Object.freeze(Object.prototype)、Object.freeze(Array.prototype)、Object.freeze(Function.prototype)等 - 配置对象优先用
Object.create(null)创建无原型对象,天然免疫污染 - 输入数据必须过滤
__proto__、constructor、prototype等敏感键名
仅在兜底场景用 try/catch 捕获,不用于主流程
若因兼容旧环境必须试探能力(如 polyfill 检测),可捕获错误并降级,但绝不作为常规逻辑:
- 错误类型一定是
TypeError,消息通常含 “prototype” 或 “extensible” - 降级方案包括:属性拷贝(
Object.assign)、代理封装(Proxy)、或切换为组合式设计 - 不要试图绕过严格模式——ES 模块默认启用,这是现代 JavaScript 的约束前提











