面试官系类:请手写instanceof

前言

本文记录instanceof运算符的手写实现。

相关文章推荐

描述

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。

语法

object instanceof constructor
复制代码

参数

  • object

    某个实例对象

  • constructor

    某个构造函数

清楚了基本信息后,下面废话不多说直接开整

1. 第一版本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

复制代码

第一版完成了主线功能,其实吧接下来要做的无非就是对函数做入参校验、边界处理、意外情况处理。比比皆是,事皆如此。

说说第一版本的问题,很明显入参需要校验

2. 第二版本instanceof

先看看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
复制代码

根据以上结果对左右入参做校验即可

function myInstanceof2(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
}

// 测试

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

console.log(myInstanceof2(1, Car)); // false
console.log(myInstanceof2('', Car)); // false
console.log(myInstanceof2(true, Car)); // false
console.log(myInstanceof2(null, Car)); // false
console.log(myInstanceof2(undefined, Car)); // false
console.log(myInstanceof2(0, Car)); // false

console.log(myInstanceof2(auto, 1)); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, '')); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, true)); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, null)); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, undefined)); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, 0)); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object
console.log(myInstanceof2(auto, {})); // Uncaught TypeError: Right-hand side of 'instanceof' is not an object


console.log(myInstanceof2(auto, Car));
// expected output: true
console.log(myInstanceof2(auto, Object));
// expected output: true

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

复制代码

看结果模拟函数基本和instanceof操作符反馈结果一致,至此关于instanceof操作符结束

3. 最终版本

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
}
复制代码

相关知识:

  • 原型,原型链相关
  • while循环
  • es6默认参数

最后

如有不明白,有疑问的欢迎拍砖!( ఠൠఠ )ノ!!!

猜你喜欢

转载自juejin.im/post/7080457287084539940