JS原型链Bug多因继承失效:一、漏写new致this绑定全局,原型方法不可用;二、直接赋值prototype覆盖constructor等内置方法;三、原型链污染使所有对象异常新增属性;四、误扩内置原型干扰遍历与第三方库。

JS 原型链 Bug 多半不是语法错误,而是运行时“看似有、实则无”的隐形问题——比如方法调用报 TypeError: xxx is not a function,或属性读取为 undefined,但代码看起来完全合理。根源往往在原型链断裂、污染或误覆盖,排查关键在于“确认对象真正继承自谁”,而非只看写了什么。
一、构造函数漏写 new 导致 this 绑定失效
这是最常见也最容易被忽略的 Bug。不加 new 调用构造函数,this 指向全局(浏览器中是 window),实例不会关联原型,所有原型方法都不可访问。
- 现象:对象能打印出来,但调用
obj.sayHello()报错is not a function - 验证方式:在控制台执行
obj.__proto__ === MyClass.prototype,返回false即确认未正确继承 - 修复建议:统一使用
new MyClass();若需支持免 new 调用,可在构造函数内加判断:if (!(this instanceof MyClass)) return new MyClass(...)
二、直接赋值 prototype 覆盖原有方法
写 MyClass.prototype = { method() {} } 会清空默认的 constructor、toString 等内置方法,下游实例调用这些方法就会失败。
- 风险点:这类写法常见于旧式类定义或配置合并逻辑中
- 安全替代:改用
Object.assign(MyClass.prototype, { method() {} })或逐个挂载MyClass.prototype.method = function() {} - 检查技巧:执行
console.log(MyClass.prototype.toString),若为undefined,说明已被覆盖
三、原型链污染引发全局行为异常
当用户输入被递归合并进普通对象(如 lodash.merge({}, userInput)),且输入含 {"__proto__": {"isAdmin": true}},就可能污染 Object.prototype,导致所有对象意外多出 isAdmin 属性。
- 典型症状:遍历对象时突然出现意料之外的属性;
{}.hasOwnProperty行为异常;某些库功能失常 - 防御手段:禁用危险键名——对所有外部输入,在解析或赋值前过滤
__proto__、constructor、prototype及其大小写变体 - 加固方案:生产环境启用
Object.freeze(Object.prototype)(注意兼容性);优先使用structuredClone替代不安全的深拷贝
四、误挂方法到 Date/String 等内置原型引发冲突
在 Date.prototype 或 String.prototype 上添加方法虽方便,但会污染全局,尤其当第三方组件依赖原生枚举行为时(如 for…in 遍历日期对象意外拿到 format 方法)。
- 事故特征:某模块突然报错,但相关代码近期无改动;错误指向看似无关的属性遍历逻辑
- 规避方式:避免扩展内置原型;如必须扩展,用
Object.defineProperty设为enumerable: false - 调试提示:检查控制台报错堆栈中是否涉及
for…in、Object.keys或第三方工具的属性遍历逻辑


















