2

We talked about instanceof in two articles about what JavaScript consists of and the first emperor in JavaScript. This article talks about instanceof

What is instanceof?

MAN 's explanation is:

The instanceof operator is used to detect whether the prototype attribute of the constructor appears on the prototype chain of an instance object

It can be seen that the left side of instanceof must be an object in order to find its prototype chain

The right side of instanceof must be a function, and the function will have a prototype attribute.

Simple example:

 function Resume(name, age, hobby) {
    this.name = name;
    this.age = age;
    this.hobby = hobby;
}

const johan = new Resume('johan', '18', 'swim');

console.log(johan instanceof Resume); // true
console.log(johan instanceof Object); // true

There is an example in Shi Huang in JavaScript :

 Object instanceof Object
Function instanceof Function

We can understand it this way, a value on a prototype chain of Object is equal to Object.prototype; a value on the prototype chain of Function is also consistent with Function.prototye;

Object instanceof Object can be understood as:

  • Object.__proto__ === Function.prototype
  • Function.prototype.__proto__ === Object.prototype
  • Object.__proto__.__proto__ === Object.prototype

Function instanceof Function can be understood as:

  • Function.__proto__ === Function.prototype

The essence is that built-in functions are created by the Function constructor, including itself

handwritten instanceof

According to the above description, namely 左边的__proto__=== 右边.prototype

first edition

 // 第一版
function myInstanceof(left, right) {
    if (left.__proto__ === right.prototype) {
        return true;
    } else {
        return false;
    }
}

console.log(myInstanceof(johan, Resume)); // true
console.log(myInstanceof(johan, Object)); // false

In the first version we implemented 左边的__proto__=== 右边.prototype . But that's not enough, myInstanceof also checks if left is on right's prototype chain. So we're going to recurse left.__proto__ . until the deepest level of the prototype chain is null

second edition

 // 第二版
function myInstanceof(left, right) {
    if (left.__proto__ === right.prototype) {
        return true;
    } else {
        if (left === null) {
            return false;
        }
        return myInstanceof(left.__proto__, right);
    }
}

3rd Edition: Consider it a primitive type

As I said at the beginning, the left side of instanceof must be an object in order to find its prototype chain

But don't forget that basic types except null and undefined are "protected" by the basic wrapper type

 var num = 1;
console.log(myInstanceof(num, Number)); // true
console.log(num instanceof Number); // false

So we need to increase the judgment of the basic type

 function myInstanceof(left, right) {
    if (typeof left !== 'object' || left === null) return false;
    if (left.__proto__ === right.prototype) {
        return true;
    } else {
        if (left === null || left.__proto__ === null) {
            return false;
        }
        return myInstanceof(left.__proto__, right);
    }
}

Look at other people's instanceof implementation

 function myInstanceof(left, right) {
    // 基本数据类型直接返回 false
    if (typeof left !== 'object' || left === null) return false;
    // getPrototype是Object对象自带的一个方法,等效于__proto__
    let proto = Object.getPrototypeOf(left);
    while (true) {
        // 循环往下寻找,知道找到相同的对象
        if (proto == null) return false;
        // 找到相同的原型对象
        if (proto == right.prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}

The usage of while is much more advanced than mine

series of articles


山头人汉波
394 声望555 粉丝