这类报错本质是原型链断裂,需显性验证构造函数、__proto__指向及逐层属性存在性,结合Object.getPrototypeOf、hasOwnProperty、getOwnPropertyDescriptors等方法定位断点。

遇到 arr.map is not a function 或 obj.toString is not a function 这类报错,本质不是方法“丢了”,而是属性查找在原型链上断了。调试的关键,是把 JavaScript 隐式的查找过程显性化、可验证。
确认对象的真实构造函数和原型指向
很多问题源于对象不是你“以为的”那种类型。比如用 Object.create(null) 创建的对象没有 Object.prototype,自然没有 toString;又比如 JSON.parse 出来的对象虽然看起来像普通对象,但它的 __proto__ 确实指向 Object.prototype,可一旦被意外赋值覆盖(如 obj.__proto__ = null),链就断了。
- 在控制台直接打印
obj.constructor,看它是否是你预期的构造函数(如Array、Object) - 检查
obj.__proto__是否为null—— 如果是,整条链已终止,任何继承方法都不可用 - 用
Object.getPrototypeOf(obj)替代直接读__proto__,更标准且兼容性好
逐层检查原型链上的属性是否存在
不要只看最终结果,要分步验证每一步是否“通”。JavaScript 的查找是“自己 → __proto__ → __proto__.__proto__ …… → null”,中间任意一环缺失都会失败。
- 先查自身:
obj.hasOwnProperty('map')或'map' in obj(注意后者包含原型链) - 再查直接原型:
obj.__proto__.hasOwnProperty('map'),如果返回false,说明该方法不在Array.prototype上(可能是被删了或污染了) - 继续向上:
Object.getPrototypeOf(obj.__proto__).hasOwnProperty('toString'),验证是否还能走到Object.prototype
警惕可枚举性与属性描述符干扰
有些属性“存在”,但查不到,是因为它们被定义为 enumerable: false,或者用了 Object.defineProperty 设置了特殊访问器。这类属性不会出现在 for...in 或 Object.keys() 中,但依然能被正常调用——除非你误判了它的存在性。
- 用
Object.getOwnPropertyDescriptors(obj)查看对象自身所有属性的完整描述(含enumerable、writable、configurable) - 用
Object.getOwnPropertyNames(obj)获取自身所有键名(包括不可枚举的),确认方法名是否真的被定义在对象上 - 若发现某个方法在
Array.prototype上却查不到,检查是否被重新赋值覆盖,例如Array.prototype.map = undefined
用 instanceof 和 isPrototypeOf 快速验证链路关系
这两个操作符不依赖属性值,只检测原型链连接本身,适合快速判断“逻辑关系是否成立”。
-
arr instanceof Array返回false?说明arr.__proto__没有指向Array.prototype,可能被手动改过或来自跨 iframe 对象 -
Array.prototype.isPrototypeOf(arr)返回false?同上,链路物理断裂 - 注意:
instanceof要求右侧必须是函数(有prototype属性),否则会抛TypeError


















