手写instanceof

8 阅读2分钟

instanceof的用法

instanceof用于检测一个对象是否是某个构造函数(或类)的实例,其核心是判断对象的原型链上是否存在该构造函数的 prototype 属性。

// 例子1:数组实例
const arr = [1,2,3];
console.log(arr instanceof Array); // true → Array.prototype 在 arr 原型链上
console.log(arr instanceof Object); // true → Object.prototype 是原型链终点

// 例子2:类实例
class Person {}
const p = new Person();
console.log(p instanceof Person); // true → Person.prototype 在 p 原型链上

// 例子3:基本类型不生效
const str = "hello";
console.log(str instanceof String); // false → 基本类型没有原型链

手写instanceof

首先来分析一下instanceof的工作原理left(对象) 的原型链上,是否存在 right(构造函数)prototype 属性

function myInstanceof(left, right) {
  // 步骤1:获取 left 的原型(对象的原型)
  let proto = Object.getPrototypeOf(left);
  // 步骤2:获取 right 的 prototype(构造函数的原型)
  const prototype = right.prototype;

  // 步骤3:循环遍历原型链
  while (true) {
    // 原型链遍历到终点(Object.prototype 的原型是 null),没找到 → false
    if (proto === null) return false;
    // 找到匹配的 prototype → true
    if (proto === prototype) return true;
    // 向上遍历:获取上一层原型
    proto = Object.getPrototypeOf(proto);
  }
}
// 测试数组
const arr = [1,2,3];
console.log(myInstanceof(arr, Array)); // true(符合预期)
console.log(myInstanceof(arr, Object)); // true(符合预期)

// 测试类实例
class Person {}
const p = new Person();
console.log(myInstanceof(p, Person)); // true(符合预期)
console.log(myInstanceof(p, Object)); // true(符合预期)

// 测试基本类型
const str = "hello";
console.log(myInstanceof(str, String)); // false(符合预期)

优化

结果正确说明,但是还可以完善一下

问题 1:如果 left 不是对象(比如基本类型),Object.getPrototypeOf 会报错吗?

  • 验证:Object.getPrototypeOf(1) → 报错(Uncaught TypeError)
  • 解决:先判断 left 是否是对象(排除 null/undefined,因为 typeof null === 'object',需要单独判断)

问题 2:如果 right 没有 prototype(比如 rightnull/undefined 或基本类型),会报错吗?

  • 验证:myInstanceof(arr, 1) → 报错(right.prototype 不存在)
  • 解决:先判断 right 是否是函数(因为只有构造函数 / 类才有 prototype 属性)
function myInstanceof(left, right) {
  // 边界处理1:left 是 null/undefined → 直接返回 false
  if (left === null || typeof left !== 'object') return false;
  // 边界处理2:right 不是函数 → 直接返回 false(构造函数必须是函数)
  if (typeof right !== 'function') return false;
  // 步骤1:获取 left 的原型(对象的原型)
  let proto = Object.getPrototypeOf(left);
  // 步骤2:获取 right 的 prototype(构造函数的原型)
  const prototype = right.prototype;

  // 步骤3:循环遍历原型链
  while (true) {
    // 原型链遍历到终点(Object.prototype 的原型是 null),没找到 → false
    if (proto === null) return false;
    // 找到匹配的 prototype → true
    if (proto === prototype) return true;
    // 向上遍历:获取上一层原型
    proto = Object.getPrototypeOf(proto);
  }
}