Search code examples
javascript

Symbol.hasInstance Property working in JS


I understand that Symbol.hasInstance property can be cutomised to check if an object is an instance of a particular class. But what i don't understand is how this is working ? Example:

class Animal {
 static [Symbol.hasInstance](obj){ // how is this obj being passes here on calling the function below
    if(obj.isAnimal) return true
 }
}

const a1 = new Animal();
console.log(a1 instanceOf Animal) // false 
a1.isAnimal = true
console.log(a1 instanceOf Animal) // true 

Question: How is obj being passed to the static function on calling a1 instanceOf Animal


Solution

  • There are many times when a function can be called even if you don't have anything in the code that does so explicitly with ()s after the property name. For example, with iterators:

    class C {
      *[Symbol.iterator]() {
        for (let i = 0; i < 3; i++) yield i;
      }
    }
    const c = new C();
    for (const item of c) {
      console.log(item);
    }

    And type coercion:

    const obj = {
      toString: () => 'some obj'
    };
    console.log(String(obj));

    And proxies.

    const prox = new Proxy({}, {
      has() {
        console.log('has invoked');
        return true;
      }
    });
    console.log('foo' in prox);

    instanceof is just another one of these circumstances.

    x instanceof y is specified to first extract the value at the hasInstance symbol from y, if such a value exists:

    1. Let instOfHandler be ? GetMethod(target, @@hasInstance).

    and then it'll be invoked with x. If the value doesn't exist,OrdinaryHasInstance will be called with x and y instead. That's all there really is to it - instanceof, by definition, will look up and try to call a Symbol.hasInstance property if there is one.

    For almost all operators, you can think of x someOperator y as invoking someOperator with x and y - and the operator often does a number of things with the operands behind the scenes.