preface

In object-oriented languages, the keyword instanceof is commonly used to detect the type of an object, or more specifically, an instanceof that type. So what’s different about this keyword in JS? This article is only an interpretation of the key word instanceof ES standard, and recorded in this process of JS object system a little perception.

What does the standard say this keyword needs to do

For example, a instanceof B. In the following steps, the value on the left of the keyword is a, and the value on the right is B.

In the standard, the behavior of instanceof is abstracted into the InstanceofOperator operation. The following two key abstractions are listed, and the steps are sorted according to my own understanding:

  • InstanceofOperator (a, b);
  • OrdinaryHasInstance (b, a);

InstanceofOperator ( a, b)

  1. Check whether b is an object. No TypeError
  2. Gets whether b defines symbol.hasinstance
  3. If yes, b[symbol.hasinstance](a) returns true or false
  4. Otherwise check whether b is a function, otherwise TypeError
  5. If yes, return the result of OrdinaryHasInstance(b, a)

OrdinaryHasInstance ( b, a )

  1. Check if b is a function, otherwise return false (this step should not be called in this scenario)
  2. If yes, check whether b is wrapped by bind. If yes, get the bind wrapped function BC and call InstanceofOperator(a, BC).
  3. If yes, check if a is an object, otherwise return false
  4. If yes, get b’s prototype attribute bp
  5. TypeError is returned if bp is not an object
  6. Get the prototype of A and assign it to A
  7. Checks if a is null, or false
  8. If a is equal to bp, return true
  9. Otherwise, repeat steps 11 to 14 until true or false is returned

A couple of details

When I looked at the standard explanation, I did not understand it very well in several places, so I used several demos to verify my understanding

What should b be

So what happens if B is not an object

The value on the right side of the object is not an object. The value on the right side of the object is not an object.

The object also reported an error. This time, the value on the right is not callable, that is, it is not a function. This should be the error detected in step 4. Follow the steps above to try setting the Symbol. HasInstance property for the object

It should be made clear that the function cannot directly set the Symbol. HasInstance attribute. For specific reasons, you can refer to the information if you are interested. B must be an object or function with a Symbol set, or an error will be reported.

A dIND – wrapped function still returns the result of the original function prototype test

The reason for this step is that, without a direct understanding of the description in the standard, it is only a guess, not sure, so verify it.

var a = function() {
   this.name = 'a';
}; 
var b = {testName: 'b'};
a.prototype = b;

var c = new a();
console.log('c instanceof a', c instanceof a);   // true

var h = {name: 'h'};
var s = a.bind(h);
console.log('c instanceof s', c instanceof s);   // true
Copy the code

Code portal

As can be seen from the running results of the code example above, A. protoType is equal to the prototype of C, and S is the function returned by A after it is bound by the object H. According to the verification results, the binding of the prototype detection is still not affected after the function is wrapped by bind.

A little thought

It’s actually quite reasonable to think of this kind of detection when you’re looking at the details above. The prototype of the object can be analogous to a Java class. What is the prototype of an object determines that it has the properties of the prototype object, and the same is true of a class. What class the object belongs to determines what properties the object has. The difference is that the detection in JS is a step back to the inheritance chain. In Java, it is directly detected whether the object is an instance of the class, while in JS, it is detected whether the object’s prototype is equal to the function’s prototype attribute. This should be the difference generated by different principles of inheritance.

I have never seriously thought about what the whole object system in JS is like before. Although I still don’t understand too much now, at least now in my cognition, JS object system is simple and perfect, and there is no lack of object-oriented basic characteristics because of simplicity. It’s flexible enough to allow you to change an object’s prototype, or class, but that doesn’t stop it from being a language that can program like objects.

conclusion

The essence of the instanceof keyword check is to check if there is an object on the prototype chain on the left that is equal to the prototype property of the function on the right, and return true if there is, or false if there is not.