instanceof 原理及实现

核心记住一句话:用来判断谁是谁的爹

1. 核心原理

instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链上的任何位置。

object instanceof Constructor

// 返回:`true` 如果 `object` 的原型链上存在 `Constructor.prototype`,否则 `false`。

2. 经典面试题:手写instanceof

/**
 * 模拟 instanceof
 * @param {Object} L 左侧对象 (实例)
 * @param {Function} R 右侧构造函数
 */
function myInstanceof(L, R) {
  // 1. 如果左侧不是对象,直接返回 false (基本类型排除)
  if (L === null || typeof L !== 'object' && typeof L !== 'function') {
    return false;
  }

  // 2. 获取右侧构造函数的原型
  const prototype = R.prototype;
  
  // 3. 获取左侧对象的原型 (Object.getPrototypeOf(L) 更好)
  let proto = Object.getPrototypeOf(L); // 或者 L.__proto__

  // 4. 循环向上查找原型链
  while (true) {
    if (proto === null) {
      return false; // 到达链顶端 (Object.prototype.__proto__ === null)
    }
    if (proto === prototype) {
      return true; // 找到了
    }
    proto = Object.getPrototypeOf(proto);
  }
}

3. 面试考点

(1) 基础类型误区

instanceof 只能正确判断引用类型 (对象),对于基本类型字面量会失效。

'hello' instanceof String // false
new String('hello') instanceof String // true

(2) 原型链查找

Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Object instanceof Function // true (最容易搞混)

解析

  • Function 是所有函数的构造函数 (包括它自己)。 Function.__proto__ === Function.prototype -> true
  • Object 本身也是一个函数。 Object.__proto__ === Function.prototype -> true

(3) iframe 跨环境问题

如果你的页面主要包含一个 iframe,iframe 中的数组和主窗口的数组是不同的构造函数。

iframe.contentWindow.Array === Array // false
const arr = new iframe.contentWindow.Array();
arr instanceof Array // false

解决方案:使用 Array.isArray()Object.prototype.toString.call(arr) === '[object Array]'

(4) Symbol.hasInstance

ES6 允许通过 static 方法自定义 instanceof 行为。

class MyArray {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}
console.log([] instanceof MyArray); // true