Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The instanceof operator is a binary operator that tests whether an object has the prototype property of a constructor function or class in its prototype chain, or if the right-hand operand implements a custom type-checking routine via Symbol.hasInstance. It evaluates the relationship by reference and returns a boolean value.
object instanceof constructor
  • object: The value (typically an object instance) to be evaluated.
  • constructor: The object, constructor function, or class against which the evaluation is performed.

Internal Mechanics

When the expression A instanceof B is evaluated, the JavaScript engine executes the internal InstanceofOperator(A, B) routine, which proceeds as follows:
  1. Target Type Check: The engine verifies that B is an object. If B is a primitive value, it throws a TypeError.
  2. Symbol.hasInstance Delegation: The engine checks if B exposes a method keyed by the well-known symbol Symbol.hasInstance.
    • If present, the engine calls this method with A as the argument, coerces the result to a boolean, and returns it.
    • Note: All standard functions and classes inherit the built-in Function.prototype[Symbol.hasInstance] method. This built-in method is what explicitly invokes the OrdinaryHasInstance routine (detailed below) to perform the standard prototype chain traversal.
  3. Callable Check: If Symbol.hasInstance is absent, the engine verifies that B is callable (possesses a [[Call]] internal method). If B is not callable, it throws a TypeError.
  4. OrdinaryHasInstance Invocation: If B is callable but lacks Symbol.hasInstance, the engine directly invokes the OrdinaryHasInstance(B, A) routine.
The OrdinaryHasInstance(C, O) routine performs the actual structural validation and prototype traversal:
  1. Bound Function Unwrapping: If C is a bound function (created via Function.prototype.bind), it lacks a prototype property. The engine extracts its internal [[BoundTargetFunction]] and recursively calls InstanceofOperator(O, [[BoundTargetFunction]]). This ensures bound functions are evaluated against their original target function’s prototype.
  2. Primitive Operand Check: The engine checks the type of O. If O is not an object (i.e., it is a primitive), the routine immediately returns false.
  3. Prototype Property Validation: The engine retrieves the prototype property of C. If C.prototype is not an object (e.g., it is undefined on an arrow function, or explicitly set to a primitive), the engine throws a TypeError.
  4. Chain Traversal: The engine retrieves the prototype of O using the internal [[GetPrototypeOf]] method (conceptually identical to Object.getPrototypeOf(O)). It recursively compares each prototype in the chain against C.prototype using strict reference equality.
  5. Termination: If a match is found, it returns true. If the traversal reaches the end of the prototype chain (null) without a match, it returns false.
function Base() {}
function Derived() {}
Object.setPrototypeOf(Derived.prototype, Base.prototype);

const instance = new Derived();

// true: Object.getPrototypeOf(instance) === Derived.prototype
console.log(instance instanceof Derived); 

// true: Object.getPrototypeOf(Object.getPrototypeOf(instance)) === Base.prototype
console.log(instance instanceof Base); 

// true: Object.prototype is at the top of the prototype chain
console.log(instance instanceof Object); 

Technical Nuances

Bound Functions Because the OrdinaryHasInstance routine unwraps bound functions before evaluating the prototype property, instanceof works seamlessly with them despite the absence of a prototype object on the bound function itself.
function Target() {}
const BoundTarget = Target.bind(null);

const instance = new Target();

// true: BoundTarget is unwrapped to Target before prototype evaluation
console.log(instance instanceof BoundTarget);
Symbol.hasInstance Override The default prototype chain traversal behavior can be intercepted and overridden. If an object exposes a custom Symbol.hasInstance method, the instanceof operator delegates the evaluation entirely to it. This allows non-callable objects to act as the right-hand operand without throwing a TypeError.
const PrimitiveNumber = {
  [Symbol.hasInstance](instance) {
    return typeof instance === 'number';
  }
};

// true: Evaluation is delegated to the custom Symbol.hasInstance method
console.log(42 instanceof PrimitiveNumber); 
Primitive Values The instanceof operator does not trigger auto-boxing for primitive values. During the OrdinaryHasInstance routine, if the left-hand operand is a primitive (string, number, boolean, symbol, bigint, null, or undefined), the operator returns false. However, because Symbol.hasInstance is evaluated before the primitive check, custom implementations can successfully return true for primitives.
"token" instanceof String; // false
new String("token") instanceof String; // true
Invalid Prototype Property If the right-hand operand is callable but lacks a valid object as its prototype property, the engine throws a TypeError during the OrdinaryHasInstance routine. This commonly occurs with arrow functions, which do not possess a prototype property.
const ArrowConstructor = () => {};

// TypeError: Function has non-object prototype 'undefined' in instanceof check
console.log({} instanceof ArrowConstructor);
Cross-Realm Execution JavaScript environments with multiple realms (such as browser windows or iframes) maintain distinct global execution contexts. Each realm has its own set of built-in constructors and prototypes. Because the default instanceof behavior relies on strict reference equality, an object instantiated in Realm A will return false when evaluated against the corresponding constructor in Realm B.
// Assuming `iframeWindow` is a reference to another realm
const iframeArray = new iframeWindow.Array();

// false: iframeArray inherits from iframeWindow.Array.prototype, not the current realm's Array.prototype
console.log(iframeArray instanceof Array); 
Master JavaScript with Deep Grasping Methodology!Learn More