value instanceof Target runs InstanceofOperator:
- If
Targetisn't an object, throw aTypeError. - Look up
Target[Symbol.hasInstance]. If it exists, call it withvalueand convert the result to a boolean. Every function inherits a default one fromFunction.prototype, so this step normally lands there. - Otherwise (no
Symbol.hasInstance),Targetmust be callable, elseTypeError. - Run
OrdinaryHasInstance(Target, value):- If
valueisn't an object, returnfalse. - If
Targetis a bound function, test against its target function instead. - Read
P = Target.prototype. IfPisn't an object, throwTypeError. - Walk
value's chain with[[GetPrototypeOf]]: returntrueon the first link that isP, andfalsewhen the chain reachesnull.
- If
So instanceof asks "is Target.prototype somewhere in value's chain right now?" It doesn't check who constructed value. Animal.prototype.isPrototypeOf(value) performs the same walk without the operator, and works when you have a prototype object but no constructor.
Consequences: reassigning Target.prototype makes old instances stop matching; Object.create(null) objects are instanceof nothing; primitives are false ('a' instanceof String) while their wrappers are true; and Symbol.hasInstance lets a class redefine the check (duck typing, "is an even number"). Objects from another realm (an iframe, vm context) have that realm's Array.prototype, so otherArray instanceof Array is false: use Array.isArray for arrays.