出处:掘金

原作者:金泽宸


面试必问:你能手写 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 仅适用于对象,原始类型(如 numberstring)会返回 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;
}

常见易错点

易错点正解
忘了处理 nulltypeof 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 可被重写的入口,了解这个能在面试中加分