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
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:
- 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.