In JavaScript, we usually use typeof to determine types, but when determining the value of a reference type, we often run into a problem: “object”(and, of course, “function”) is returned no matter what typeof object is referenced. Instanceof comes in handy when we need to know whether the reference object is an array or a wrapper object.

Without further ado, let’s warm up with a few examples. If you know all of them, please click the close button in the upper right corner; For those of you who are confused, you can keep reading, but if you know the principles, these questions are really easy.

const a = 'abc';
console.log(a instanceof String); // ?

const b = new String('abc');
console.log(b instanceof String); // ?
Copy the code
console.log(String instanceof String);  // ?
console.log(Object instanceof Object);  // ?
console.log(Function instanceof Function); // ?
console.log(Function instanceof Object); // ?
Copy the code

How does Instanceof work

Instanceof is described in MDN as follows:

The instanceof operator tests whether the constructor’s Prototype property appears anywhere in the object’s prototype chain

In other words, if A is instanceof B, then A must be an object and B must be A legitimate JavaScript function. When both conditions are met:

Check whether B’s prototype property points to A prototype object (B. protoType) that is on the prototype chain of object A.

If yes, true; If not, false.

Let’s take an example step by step:

function Person() {} 
const p1 = new Person();

p1 instanceof Person; // true
Copy the code

Step 1: Each constructor has a Prototype property.

Step 2: The Prototype property points to the constructor’s prototype object

Step 3: With the new keyword, you can create an instance of the constructor (p1 in this case) with a __proto__ attribute on each instance

Step 4: The __proto__ property on the instance also points to the constructor’s prototype object, so we can get a complete diagram

Step 5: p1 instanceof Person, check whether the prototype object pointed to by the prototype property of B(Person) is on the prototype chain of object A(p1).

After step by step decomposition, we found that the prototype object pointed to by the prototype of B(Person) is indeed on the prototype chain of A(P1), so we can confirm that P1 instanceof Person must be true.

If we dig a little deeper, not only is p1 instanceof Person true, but p1 instanceof Object is also true. Why is that?

The Person prototype Object has a __proto__ property that points to the prototype Object’s prototype property.

Since this relationship exists, let’s improve the above diagram:

From the Person example, we know that the prototype property on the Object constructor points to its prototype Object:

Now, we need to judge whether P1 instanceof Object is true or false. Remember the above definition? Let’s try it again:

Check whether B’s prototype property points to A prototype object (B. protoType) that is on the prototype chain of object A.

If yes, true; If not, false.

At this point, we find that the prototype Object pointed to by the prototype property of B(Object) is still on the prototype chain of A(p1), so the result is true.

From the above example, we can know that the principle of Instanceof is actually very simple, which is a process of searching the prototype chain. Therefore, as long as you understand the relevant knowledge of the prototype chain, there will be no problem in understanding the principle of Instanceof. Here’s a quick summary of two prototype chains related to Instanceof:

  1. All JavaScript objects have it__proto__Attributes, onlyObject.prototype.__proto__ === null
  2. constructionalprototypeProperty refers to its prototype object, while the constructor instance__proto__Property also points to the stereotype object;

How to implement an instanceof?

It’s easy to see how instanceof can be implemented:

function instance_of(left, right) {
  const RP = right.prototype; // The prototype of the constructor
  while(true) {
    if (left === null) {
      return false;
    }
    if (left === RP) { // Be sure to compare strictly
      return true;
    }
    left = left.__proto__; // Reassign along the prototype chain}}Copy the code

With the above implementation in mind, let’s explain the above example:

function Person() {}
const p1 = new Person();
p1 instanceof Object; // Explain it with the code above
Copy the code

First assignment

left = p1
right = Object
RP = Object.prototype
Copy the code

First judgment

left ! == null and left! == RP, continue to look up the left prototype chain and prepare the new assignment.

The second assignment

left = p1.__proto__ = Person.prototype
Copy the code

Second judgment

left ! == null and left! == RP, continue to look up the left prototype chain and prepare the new assignment.

The third assignment

left = p1.__proto__.__proto__ = Person.prototype.__proto__
Copy the code

The third assignment

left ! == null, left === RP, return true, the function completes.

Third, summary

Today, we use an example to analyze the implementation principle of Instanceof from two perspectives of drawing and code implementation. In fact, the idea is very simple, nothing more than a process of searching up the prototype chain. I hope you don’t get caught up in the “What’s the implementation of Instanceof? This kind of interview is difficult.

Of course, reading is always going to be a very passive way of learning, and I recommend that you practice it yourself. There are several examples at the beginning of the article. If you are interested, you can choose an example and deepen your understanding by drawing pictures and implementing codes. I believe you will have a deeper understanding.

If the article is wrong or not precise, welcome to correct.

Finally, the article will be first published on my Github, welcome to follow.