Skip to content

instanceof 模拟

可以使用 Object.getPrototypeOf 查找原型,来比对 A 是否 instanceof B。

js
function instanceofMock(before, after) {
  // 检查参数
  if (typeof before !== 'object' || before === null) {
    return false
  }
  if (typeof after !== 'function') {
    return false
  }

  let current = before

  while (current) {
    // 一直往原型链上面找
    if (Object.getPrototypeOf(current) === after.prototype) {
      return true
    }

    current = Object.getPrototypeOf(current)
  }

  return false
}
js
function grandpa() {
  this.a = 1
}

function father() {
  this.b = 2
}

function son() {
  grandpa.call(this)
  father.call(this)
  this.c = 3
}

father.prototype = Object.create(grandpa.prototype)
// 重新指定 constructor
father.prototype.constructor = father

son.prototype = Object.create(father.prototype)
// 重新指定 constructor
son.prototype.constructor = son

const sub = new son()
console.log(sub)

console.log(instanceofMock(sub, son))
console.log(instanceofMock(sub, father))
console.log(instanceofMock(sub, grandpa))

运行结果

1 2 3
son { a: 1, b: 2, c: 3 }
true
true
true

实现原理

其实 instanceof 主要的实现原理是 before__proto__after 的原型链上即可。

所以 instanceof 在查找的过程中会遍历 before 的原型链,直到找到和 afterprototype 相等,会返回 true,如果查找失败,则会返回 false

下面是几个有趣的例子:

js
function Foo() {}

Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true

要想全部理解 instanceof 的原理,除了刚刚提到的实现原理,还需要知道 JavaScript 的原型继承原理。

JavaScript Object Layout - Hursh Jain/mollypages.org

根据上面的原型图可知:

js
before = Object.__proto__ // Function.prototype
after = Object.prototype

// 第一次判断
before != after
before = Function.prototype.__proto__ // Object.prototype

// 第二次判断
before === after
// 返回 true
js
let before = Foo
let after = Foo

before = Foo.__proto // Function.prototype
after = Foo.prototype

// 第一次判断
before != after
before = Function.prototype.__proto__ // Object.prototype

// 第二次判断
before != after
before = Object.prototype // null

// 第三次判断
before === null
// 返回 false
js
let before = Foo
let after = Object

before = Foo.__proto__ // Function.prototype
after = Object.prototype

// 第一次判断
before != after
before = Function.prototype.__proto__ // Object.prototype

// 第二次判断
before === after
// 返回 true
js
let before = Foo
let after = Function

before = Foo.__proto__ // Function.prototype
after = Function.prototype

// 第一次判断
before === after
// 返回 true