instanceof:JavaScript 原型链视角下的引用类型检测方法

1. 基本定义与语法

instanceof 是 JavaScript 中的二元运算符,用于检测构造函数的原型是否出现在对象的原型链中:

object instanceof Constructor

  • 若返回 true,表示 object 是通过 Constructor 或其子类创建的实例。
  • 若返回 false,则对象与构造函数无原型链关联。
2. 原型链检测原理

设对象 $O$ 和构造函数 $C$,instanceof 的核心逻辑如下: $$ \begin{aligned} \text{检测过程:} & \ 1.\ & \text{获取 } C\text{ 的原型:} \quad \text{proto}_C = C.prototype \ 2.\ & \text{获取 } O\text{ 的原型链:} \quad \text{currentProto} = O.__proto__ \ 3.\ & \text{遍历原型链直至匹配或到达终点:} \ & \quad \text{while (currentProto !== null) } { \ & \quad \quad \text{if (currentProto === proto}_C\text{) return true} \ & \quad \quad \text{currentProto = currentProto.__proto__} \ & \quad } \ & \text{return false} \end{aligned} $$

3. 关键特性
  • 依赖原型链:检测基于动态原型链,非静态类型。
    function Person() {}
    const p = new Person();
    console.log(p instanceof Person); // true
    

  • 继承关系检测:子类实例对父类构造函数返回 true
    class Student extends Person {}
    const s = new Student();
    console.log(s instanceof Person); // true(Student 原型链包含 Person.prototype)
    

  • 边界情况
    • 基本类型直接返回 false(无原型链):
      console.log(123 instanceof Number); // false
      

    • 显式修改原型链可改变结果:
      const obj = {};
      obj.__proto__ = Array.prototype;
      console.log(obj instanceof Array); // true
      

4. typeof 的对比
特性 instanceof typeof
检测目标 对象与构造函数的关系 值的基本类型
返回值 boolean 类型字符串(如 "object"
示例 [] instanceof Arraytrue typeof []"object"
5. 应用场景
  1. 类型校验:验证自定义类实例。
    class Logger {}
    function log(message) {
      if (!(message instanceof Logger)) {
        throw new Error("Invalid message type");
      }
      // 处理逻辑
    }
    

  2. 多态处理:根据原型链执行不同操作。
    if (vehicle instanceof Car) {
      vehicle.accelerate();
    } else if (vehicle instanceof Boat) {
      vehicle.sail();
    }
    

6. 局限性
  • 跨执行环境失效:不同 iframe 或窗口的构造函数不共享原型。
    // 在 iframe 中创建的数组
    const iframeArray = frame.contentWindow.Array;
    const arr = new iframeArray();
    console.log(arr instanceof Array); // false(因 window.Array !== frame.contentWindow.Array)
    

  • 手动修改原型导致误判
    function A() {}
    function B() {}
    A.prototype = B.prototype = {};
    const a = new A();
    console.log(a instanceof B); // true(原型相同)
    

7. 替代方案
  • Object.prototype.toString():更稳定的类型检测。
    console.log(Object.prototype.toString.call([])); // "[object Array]"
    

  • ES6 Symbol.hasInstance:自定义 instanceof 行为。
    class Custom {
      static [Symbol.hasInstance](obj) {
        return obj.hasOwnProperty('isCustom');
      }
    }
    const x = { isCustom: true };
    console.log(x instanceof Custom); // true
    

总结

instanceof 通过原型链动态检测对象与构造函数的关联,适用于面向对象编程中的类型校验,但需注意跨环境限制和原型篡改风险。在复杂场景中,建议结合 Object.prototype.toString()Symbol.hasInstance 增强可靠性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐