出处:掘金
原作者:金泽宸
面试必问:你能手写 instanceof
吗?
面试官为什么问这个问题:
- 想知道你是否理解 JS 的原型链查找机制
- 能否用循环/递归 + 原型指针逻辑模拟语言行为
工作原理(基于原型链)
a instanceof B
本质判断的是:B.prototype
是否在 a.__proto__
的原型链上。即:
a.__proto__ === B.prototype
a.__proto__.__proto__ === B.prototype
a.__proto__.__proto__.__proto__ === B.prototype
// ...
// 直到 __proto__ === null 为止
注意事项
- 左值原始值无效:
instanceof
仅适用于对象,原始类型(如number
、string
)会返回false
console.log('str' instanceof String); // false,需用 new String() 创建对象
- 右值原始值报错:
({}) instanceof null; // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
- 跨框架问题:不同窗口或框架中的相同构造函数可能拥有不同的原型链,导致检测失效
- 构造函数修改风险:若手动修改构造函数的
prototype
属性,可能导致instanceof
结果异常
手写 instanceof
function myInstanceof(obj, constructor) {
if (typeof obj !== 'object' || obj === null) return false;
if (typeof constructor !== 'object' || constructor === null) {
throw new TypeError(`Right-hand side of 'instanceof' is not an object`);
}
let proto = Object.getPrototypeOf(obj); // 相当于 obj.__proto__
const prototype = constructor.prototype;
while (proto) { // 当proto == null 时,说明已经找到了 Object 的基类 null,退出循环
if (proto === prototype) return true;
proto = Object.getPrototypeOf(proto); // 向上查找
}
return false;
}
常见易错点
易错点 | 正解 |
---|---|
忘了处理 null | typeof obj !== 'object' || obj === null |
直接 __proto__ | 推荐用 Object.getPrototypeOf() 更规范 |
判断条件错误 | proto === constructor.prototype ,不要搞混 |
进阶加分项
实际上 a instanceof B
会调用:
B[Symbol.hasInstance](a)
你甚至可以这样 hack:
class A {
static [Symbol.hasInstance](obj) {
return false;
}
}
console.log(new A() instanceof A); // false !!!
这是 instanceof
可被重写的入口,了解这个能在面试中加分