instanceof 原理实现

手写 JavaScript 的 instanceof 操作符

问题

手写实现 instanceof 操作符,判断对象是否是某个构造函数的实例。

解答

instanceof 的原理是沿着对象的原型链查找,判断构造函数的 prototype 是否在原型链上。

function myInstanceof(obj, constructor) {
  // 基本类型直接返回 false
  if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
    return false;
  }

  // 获取构造函数的 prototype
  const prototype = constructor.prototype;

  // 获取对象的原型
  let proto = Object.getPrototypeOf(obj);

  // 沿原型链向上查找
  while (proto !== null) {
    if (proto === prototype) {
      return true;
    }
    proto = Object.getPrototypeOf(proto);
  }

  return false;
}

测试用例

function Person(name) {
  this.name = name;
}

const p = new Person('Tom');

console.log(myInstanceof(p, Person));   // true
console.log(myInstanceof(p, Object));   // true
console.log(myInstanceof(p, Array));    // false

console.log(myInstanceof([], Array));   // true
console.log(myInstanceof([], Object));  // true

// 基本类型
console.log(myInstanceof(1, Number));       // false
console.log(myInstanceof('str', String));   // false
console.log(myInstanceof(null, Object));    // false

使用 __proto__ 的写法

function myInstanceof(obj, constructor) {
  if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
    return false;
  }

  let proto = obj.__proto__;

  while (proto) {
    if (proto === constructor.prototype) {
      return true;
    }
    proto = proto.__proto__;
  }

  return false;
}

关键点

  • instanceof 检查构造函数的 prototype 是否在对象的原型链上
  • 基本类型(非对象)直接返回 false
  • 使用 Object.getPrototypeOf()__proto__ 更规范
  • 原型链的终点是 null,作为循环终止条件
  • 所有对象都是 Object 的实例(除了 Object.create(null) 创建的对象)