instanceof 的核心是沿实例的原型链向上查找是否等于构造函数的 prototype;手写需先判空和非对象,再用 while 遍历原型链比对,避免栈溢出与类型错误。

手写 instanceof 的核心,就是沿着构造函数的 prototype 和实例的 __proto__(或 Object.getPrototypeOf())向上遍历原型链,逐层比对是否相等。
原型链比对的本质逻辑
JavaScript 中,a instanceof B 成立的条件是:从 a 的原型开始,沿 __proto__ 一路向上查找,**中途某一级原型 === B.prototype**。只要找到就返回 true;查到顶层(null)还没找到,就返回 false。
注意:instanceof 不比较构造函数本身,而是比对「实例的隐式原型链」和「构造函数的显式原型对象」是否在同一条路径上。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
递归实现的关键步骤
- 获取实例对象的当前原型:
let proto = Object.getPrototypeOf(left)(避免直接用__proto__,更标准) - 判断是否匹配:
if (proto === right.prototype) return true - 若不匹配且未到链顶(
proto !== null),递归调用自身,传入proto作为新的左操作数 - 若
proto === null,说明已到原型链终点,返回false
完整手写代码示例
(支持基本类型、函数、自定义类,兼容 ES5+)
立即学习“Java免费学习笔记(深入)”;
function myInstanceof(left, right) {
if (typeof left !== 'object' || left === null) return false;
let proto = Object.getPrototypeOf(left);
while (proto !== null) {
if (proto === right.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
}
✅ 使用 while 循环比递归更安全(避免深层原型链导致栈溢出)
✅ 先判空和非对象,防止对 undefined、number 等调用 getPrototypeOf 报错
✅ 每次只取当前对象的直接原型,严格遵循 JS 原型链查找规则
容易忽略的边界情况
-
null和undefined:它们没有原型,直接返回false - 原始值(如
123、"abc"):会被自动包装,但myInstanceof(123, Number)在手写中需先做装箱处理,否则Object.getPrototypeOf(123)会报错 —— 所以开头的typeof判断必不可少 - 箭头函数无
prototype:若right是箭头函数,right.prototype是undefined,比对必为false,符合原生行为

















