要我自己实现 instanceof 方法?

834 阅读1分钟

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,如object instanceof constructor ,具体是检测 constructor.prototype  是否存在于参数 object 的原型链上。


害,这多简单呀

function myinstanceof(a,b){  
     return a instanceof b
}

集美们别打我,这我是故意的,下次还敢。


呃呃,那它既然是通过查找原型链的方式来检测,那我们也就来实现一个 instanceof ,先了解获取原型的方法 Object.getPrototypeOf(a) 方法。

let arr = []; 
console.log(Object.getPrototypeOf(arr) === arr.__proto__) //true

下面这段代码就是通过原型链查找的方式来实现的,第二个参数必须为构造函数。

function myinstanceof(a, b) {
    let prototypeA = Object.getPrototypeOf(a),
        prototypeB = b.prototype;

    while (prototypeA) {
        if (prototypeA === prototypeB) return true;
        prototypeA = Object.getPrototypeOf(prototypeA);
    }
    return false
}

let arr = [];
let obj = {};
console.log(myinstanceof(Array, Object)) // true
console.log(myinstanceof(arr, Object)) // true
console.log(myinstanceof(arr, obj)) // false
console.log(myinstanceof(obj, arr)) // false

也没什么,就是获取到原型后,按照原型链向上查找,对比他们两的原型是否相等,一直查到 null 为止。


更绕点的代码是下面的,并处理了传入非构造函数的情况,能看懂下面实现方式那原型链这块知识已经很扎实了。

function myinstanceof(a,b){ 

    let prototypeA = typeof a == 'function' ? a.prototype : a
    let prototypeB = typeof b == 'function' ? b.prototype : b
     
    while(prototypeA != null ){  
        if(prototypeA.constructor.name === prototypeB.constructor.name) return true  
        prototypeA = prototypeA.__proto__;
    }
      
    return false
}

let arr = [];
let obj = {}; 

console.log(myinstanceof(Array,Object)) // true
console.log(myinstanceof(arr, Object)) // true
console.log(myinstanceof(arr, obj)) // true
console.log(myinstanceof(obj, arr)) // false

可以看到第二个参数传入非构造函数也可以被识别,这是因为上面代码经过处理,将传入的非构函数转换为函数后,在进行检测,当然,检测 b(或他的构造函数)否存在于 a 的原型链中,顺序反了也是不行的。