手写instanceof

127 阅读2分钟

instanceof描述

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。简单来说就是一个实列对象是否在某个构造函数的原型上面。

代码演示

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);

console.log(auto instanceof Car);
// expected output: true

console.log(auto instanceof Object);
// expected output: true

第一版instanceof

function myInstanceof1(L, R) {
    // 声明一个变量获取对象的__proto__
    let link = L.__proto__
    // 做循环(当link最终指向null,如果指向null的情况下都找不到那就返回false)
    while (link !== null) {
        // 如果找到说明R.prototype在L的原型链上,即返回true
        if(link === R.prototype) return true
        // 逐级向下
        link = link.__proto__
    }
    return false
}

// 测试

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);

console.log(myInstanceof1(auto, Car)); // true
console.log(myInstanceof1(auto, Object)); // true

console.log(auto instanceof Car); // true
console.log(auto instanceof Object); // true


主要功能实现接下来对一些特殊情况进行判断。

先看看instanceof如何处理左右两侧的参数问题

1 instanceof Number // false
'' instanceof String // false
true instanceof Boolean // false
null instanceof Boolean // false
NaN instanceof Number // false
undefined instanceof Number // false
0 instanceof Number // false

可以看到对于左侧参数无论你输入什么类型的参数instanceof都是正常执行。来试试右侧

var a = {}
a instanceof 1 // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof '' // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof true // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof null // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof NaN // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof undefined // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof 0 // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
a instanceof {} // Uncaught TypeError: Right-hand side of 'instanceof' is not callable

从上来的判断可知

  • 当左边不是一个对象的时候直接返回false。
  • 当右边不是一个函数或者没有原型的时候直接报错。

最终版本

function myInstanceof(L = null, R) {
    // 对于左侧参数如果是非对象直接返回false
    if (Object(L) !== L) return false
    // 对于右侧参数可以认为只能为函数且不能没有Prototype属性
    if (typeof R !== 'function' || !R.prototype) throw new TypeError('Right-hand side of 'instanceof' is not an object')
    // 声明一个变量获取对象的__proto__
    let link = L.__proto__
    // 做循环(当link最终指向null,如果指向null的情况下都找不到那就返回false)
    while (link !== null) {
        // 如果找到说明R.prototype在L的原型链上,即返回true
        if(link === R.prototype) return true
        // 逐级向下
        link = link.__proto__
    }
    return false
}