|

JavaScript 38 🧬 instanceof operator

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

console.log(dog instanceof Dog);      // true
console.log(dog instanceof Animal);   // true
console.log(dog instanceof Object);   // true

console.log(dog instanceof Array);    // false

const arr = [1, 2, 3];
console.log(arr instanceof Array);    // true
console.log(arr instanceof Object);   // true

console.log([] instanceof Object);    // true
console.log({} instanceof Object);    // true
console.log("hello" instanceof String);  // false (primitive)
console.log(new String("hello") instanceof String);  // true (object)

The instanceof operator checks whether an object was created by a specific constructor — or more precisely, whether that constructor’s prototype appears anywhere in the object’s prototype chain. It’s the standard way to ask “is this a Date?”, “is this an Array?”, “is this a Dog?”.

Key point: instanceof walks the prototype chain. If the constructor’s prototype is anywhere up the chain, the result is true. This is why dog instanceof Animal works — Dog extends Animal, so Animal.prototype is in dog‘s chain.


a – What is instanceof and how it works

instanceof is a binary operator that takes an object on the left and a constructor (or class) on the right. It returns true or false.

Basic syntax:

object instanceof Constructor

Example:

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

console.log(dog instanceof Dog);      // true
console.log(dog instanceof Animal);   // true
console.log(dog instanceof Object);   // true
console.log(dog instanceof Array);    // false

How it works — walking the prototype chain:

When you write dog instanceof Dog, JavaScript does this:

  1. Take Dog.prototype
  2. Start at dog.__proto__
  3. Walk up the chain: dog.__proto__, dog.__proto__.__proto__, …
  4. If any link equals Dog.prototype, return true
  5. If you reach null, return false
┌──────────────────────────────────────────────┐
│           dog's prototype chain              │
│                                              │
│  dog                                         │
│   │                                          │
│   ▼                                          │
│  Dog.prototype      ← instanceof Dog ✅      │
│   │                                          │
│   ▼                                          │
│  Animal.prototype   ← instanceof Animal ✅   │
│   │                                          │
│   ▼                                          │
│  Object.prototype   ← instanceof Object ✅   │
│   │                                          │
│   ▼                                          │
│  null                                        │
│                                              │
└──────────────────────────────────────────────┘

This is why dog instanceof Animal is trueAnimal.prototype is in the chain even though dog was created by Dog.

instanceof vs typeof:

Aspecttypeofinstanceof
OperandAny valueObject + constructor
ReturnsStringBoolean
PrimitivesDetects themAlways false
Custom classes"object" — uselessWorks correctly
Arrays"object" — wronginstanceof Array
null"object" — bugnull instanceof Xfalse
console.log(typeof []);           // "object"  — not helpful
console.log([] instanceof Array); // true      — useful

console.log(typeof null);         // "object"  — historical bug
console.log(null instanceof Object); // false  — correct

console.log(typeof "hi");         // "string"
console.log("hi" instanceof String); // false  — primitive

instanceof and primitives:

instanceof only works on objects. Primitives return false even when wrapped:

console.log("hello" instanceof String);            // false
console.log(new String("hello") instanceof String); // true
console.log(42 instanceof Number);                 // false
console.log(true instanceof Boolean);              // false

If you need to check a primitive’s type, use typeof.

instanceof with built-in types:

console.log([] instanceof Array);         // true
console.log({} instanceof Object);        // true
console.log(new Date() instanceof Date);  // true
console.log(/abc/ instanceof RegExp);     // true
console.log(new Map() instanceof Map);    // true
console.log(new Set() instanceof Set);    // true
console.log((function(){}) instanceof Function); // true

instanceof with null and undefined:

console.log(null instanceof Object);       // false
console.log(undefined instanceof Object);  // false

Never throws — always returns false.


b – instanceof with classes and inheritance

instanceof shines when you have class hierarchies. It tells you whether an object belongs to a class or any of its ancestors.

Class hierarchy:

class Animal {
  speak() { return 'sound'; }
}

class Dog extends Animal {
  speak() { return 'woof'; }
}

class Cat extends Animal {
  speak() { return 'meow'; }
}

const dog = new Dog();
const cat = new Cat();

console.log(dog instanceof Dog);      // true
console.log(dog instanceof Animal);   // true
console.log(dog instanceof Cat);      // false

console.log(cat instanceof Cat);      // true
console.log(cat instanceof Animal);   // true
console.log(cat instanceof Dog);      // false

The hierarchy:

       Animal
       /    \
     Dog    Cat
      │      │
     dog    cat

dog is an instance of Dog, Animal, and Object. It’s not an instance of Cat or Array.

Multiple levels of inheritance:

class A {}
class B extends A {}
class C extends B {}

const c = new C();

console.log(c instanceof C);  // true
console.log(c instanceof B);  // true
console.log(c instanceof A);  // true
console.log(c instanceof Object);  // true

The chain walks all the way up.

instanceof for type guards:

function describe(animal) {
  if (animal instanceof Dog) {
    return 'A dog: ' + animal.speak();
  }
  if (animal instanceof Cat) {
    return 'A cat: ' + animal.speak();
  }
  if (animal instanceof Animal) {
    return 'Some animal: ' + animal.speak();
  }
  return 'Not an animal';
}

console.log(describe(new Dog()));    // A dog: woof
console.log(describe(new Cat()));    // A cat: meow
console.log(describe(new Animal())); // Some animal: sound
console.log(describe({}));           // Not an animal

Order matters: Check the most specific class first. If you checked Animal before Dog, every Dog would match Animal and you’d never reach the Dog branch.

instanceof with custom errors:

class ValidationError extends Error {}
class NetworkError extends Error {}

try {
  throw new ValidationError('Invalid email');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log('Validation problem:', err.message);
  } else if (err instanceof NetworkError) {
    console.log('Network problem:', err.message);
  } else if (err instanceof Error) {
    console.log('Other error:', err.message);
  }
}
// [ Validation problem: Invalid email ]

This is the idiomatic way to handle custom error types.

instanceof with abstract-like base classes:

class Shape {
  area() { throw new Error('Not implemented'); }
}
class Circle extends Shape {
  constructor(r) { super(); this.r = r; }
  area() { return Math.PI * this.r ** 2; }
}
class Square extends Shape {
  constructor(s) { super(); this.s = s; }
  area() { return this.s ** 2; }
}

function printArea(shape) {
  if (!(shape instanceof Shape)) {
    throw new TypeError('Expected a Shape');
  }
  console.log(shape.area().toFixed(2));
}

printArea(new Circle(5));  // 78.54
printArea(new Square(4));  // 16.00

try {
  printArea({});
} catch (e) {
  console.log(e.message);
}
// [ Expected a Shape ]

Subclass instance checks:

class Vehicle {}
class Car extends Vehicle {}
class ElectricCar extends Car {}

const tesla = new ElectricCar();

console.log(tesla instanceof ElectricCar);  // true
console.log(tesla instanceof Car);          // true
console.log(tesla instanceof Vehicle);      // true
console.log(tesla instanceof Object);       // true

Overriding Symbol.hasInstance:

You can customize instanceof for a class by defining Symbol.hasInstance:

class EvenNumber {
  static [Symbol.hasInstance](value) {
    return typeof value === 'number' && value % 2 === 0;
  }
}

console.log(2 instanceof EvenNumber);   // true
console.log(3 instanceof EvenNumber);   // false
console.log(4 instanceof EvenNumber);   // true

Now instanceof EvenNumber doesn’t walk the prototype chain — it runs your custom check. This is powerful but rare.

instanceof does not work across realms:

Objects created in a different realm (iframe, Worker, VM) have different Array, Object, etc. constructors, so instanceof fails:

// In a browser, an array from an iframe
iframeArray instanceof Array;  // false — different Array constructor

Use Array.isArray() for cross-realm array checks.


c – instanceof vs alternatives

instanceof is one tool among several. Knowing when to use something else prevents bugs.

instanceof vs typeof:

typeof 42              // "number"
typeof "hi"            // "string"
typeof true            // "boolean"
typeof undefined       // "undefined"
typeof null            // "object"  ← famous bug
typeof []              // "object"
typeof {}              // "object"
typeof function(){}    // "function"

typeof is for primitives and "function". Use instanceof for custom classes and built-ins.

instanceof vs Array.isArray:

console.log([] instanceof Array);    // true
console.log(Array.isArray([]));      // true

Both work, but Array.isArray() is cross-realm safe — it works with arrays from iframes and Workers.

// In a browser
iframe.contentWindow.Array === Array;  // false
iframeArray instanceof Array;          // false ❌
Array.isArray(iframeArray);            // true ✅

Use Array.isArray() when you might receive arrays from another realm.

instanceof vs constructor:

const arr = [];
console.log(arr.constructor === Array);   // true
console.log(arr instanceof Array);        // true

.constructor is fragile — it can be overwritten:

arr.constructor = Object;
console.log(arr.constructor === Array);   // false ❌
console.log(arr instanceof Array);        // true ✅

instanceof is more robust.

instanceof vs Object.prototype.toString.call:

const tag = Object.prototype.toString.call([]);
console.log(tag);  // "[object Array]"

This is the oldest and most portable type check. It works across realms but is verbose. Modern code prefers instanceof for objects and typeof for primitives.

instanceof vs duck typing:

Duck typing asks “does it behave like X?” instead of “was it made by X?”

// instanceof
if (obj instanceof Array) { ... }

// duck typing
if (typeof obj.length === 'number' && typeof obj.push === 'function') { ... }

Duck typing is more flexible (works with array-likes) but less precise.

Comparison table:

CheckUse forCross-realm
typeofPrimitives, functions
instanceofCustom classes, built-ins
Array.isArrayArrays
.constructorQuick check❌ (mutable)
Object.prototype.toStringPortable type detection
Duck typingInterface-like checks

When to use instanceof:

  • Checking custom class membership
  • Checking error subclasses in catch
  • Type guards in functions
  • Anywhere the object was created in the same realm

When to use something else:

  • Primitives → typeof
  • Arrays across realms → Array.isArray
  • Portable detection → Object.prototype.toString
  • Behavior-based checks → duck typing

Complete Example Session

// ============================================
// PART 1: BASIC INSTANCEOF
// ============================================

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

console.log(dog instanceof Dog);
// [ true ]

console.log(dog instanceof Animal);
// [ true ]

console.log(dog instanceof Object);
// [ true ]

console.log(dog instanceof Array);
// [ false ]

// ============================================
// PART 2: BUILT-IN TYPES
// ============================================

const arr = [1, 2, 3];
console.log(arr instanceof Array);
// [ true ]

console.log(arr instanceof Object);
// [ true ]

console.log([] instanceof Object);
// [ true ]

console.log({} instanceof Object);
// [ true ]

// ============================================
// PART 3: PRIMITIVES
// ============================================

console.log("hello" instanceof String);
// [ false ]

console.log(new String("hello") instanceof String);
// [ true ]

console.log(42 instanceof Number);
// [ false ]

// ============================================
// PART 4: NULL AND UNDEFINED
// ============================================

console.log(null instanceof Object);
// [ false ]

console.log(undefined instanceof Object);
// [ false ]

// ============================================
// PART 5: HIERARCHY
// ============================================

class A {}
class B extends A {}
class C extends B {}

const c = new C();

console.log(c instanceof C);
// [ true ]
console.log(c instanceof B);
// [ true ]
console.log(c instanceof A);
// [ true ]
console.log(c instanceof Object);
// [ true ]

// ============================================
// PART 6: SIBLINGS
// ============================================

class Dog2 extends Animal {}
class Cat2 extends Animal {}

const d = new Dog2();
const cat = new Cat2();

console.log(d instanceof Dog2);
// [ true ]
console.log(d instanceof Cat2);
// [ false ]
console.log(d instanceof Animal);
// [ true ]

// ============================================
// PART 7: TYPE GUARDS
// ============================================

function describe(animal) {
  if (animal instanceof Dog2) return 'dog';
  if (animal instanceof Cat2) return 'cat';
  if (animal instanceof Animal) return 'animal';
  return 'unknown';
}

console.log(describe(new Dog2()));
// [ dog ]
console.log(describe(new Cat2()));
// [ cat ]
console.log(describe(new Animal()));
// [ animal ]
console.log(describe({}));
// [ unknown ]

// ============================================
// PART 8: CUSTOM ERRORS
// ============================================

class ValidationError extends Error {}
class NetworkError extends Error {}

function throwError(type) {
  if (type === 'v') throw new ValidationError('bad input');
  if (type === 'n') throw new NetworkError('no connection');
}

try {
  throwError('v');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log('Validation:', err.message);
  }
}
// [ Validation: bad input ]

// ============================================
// PART 9: VS TYPEOF
// ============================================

console.log(typeof []);
// [ object ]
console.log([] instanceof Array);
// [ true ]

console.log(typeof null);
// [ object ]
console.log(null instanceof Object);
// [ false ]

// ============================================
// PART 10: ARRAY.ISARRAY
// ============================================

console.log([] instanceof Array);
// [ true ]
console.log(Array.isArray([]));
// [ true ]

// ============================================
// PART 11: CONSTRUCTOR PROPERTY
// ============================================

const a = [];
console.log(a.constructor === Array);
// [ true ]

a.constructor = Object;
console.log(a.constructor === Array);
// [ false ]  ← fragile
console.log(a instanceof Array);
// [ true ]   ← robust

// ============================================
// PART 12: SYMBOL.HASINSTANCE
// ============================================

class EvenNumber {
  static [Symbol.hasInstance](value) {
    return typeof value === 'number' && value % 2 === 0;
  }
}

console.log(2 instanceof EvenNumber);
// [ true ]
console.log(3 instanceof EvenNumber);
// [ false ]

// ============================================
// PART 13: DATE / REGEXP / MAP
// ============================================

console.log(new Date() instanceof Date);
// [ true ]
console.log(/abc/ instanceof RegExp);
// [ true ]
console.log(new Map() instanceof Map);
// [ true ]
console.log(new Set() instanceof Set);
// [ true ]

// ============================================
// PART 14: FUNCTIONS
// ============================================

console.log(function(){} instanceof Function);
// [ true ]
console.log(() => {} instanceof Function);
// [ true ]

// ============================================
// PART 15: CHAIN CHECK
// ============================================

class Base {}
class Mid extends Base {}
class Leaf extends Mid {}

const leaf = new Leaf();

console.log(leaf instanceof Leaf);
// [ true ]
console.log(leaf instanceof Mid);
// [ true ]
console.log(leaf instanceof Base);
// [ true ]
console.log(leaf instanceof Object);
// [ true ]

// ============================================
// PART 16: SHAPE EXAMPLE
// ============================================

class Shape {}
class Circle extends Shape {
  constructor(r) { super(); this.r = r; }
}
class Square extends Shape {
  constructor(s) { super(); this.s = s; }
}

function checkShape(s) {
  if (s instanceof Circle) return 'circle';
  if (s instanceof Square) return 'square';
  if (s instanceof Shape) return 'shape';
  return 'not a shape';
}

console.log(checkShape(new Circle(5)));
// [ circle ]
console.log(checkShape(new Square(4)));
// [ square ]
console.log(checkShape(new Shape()));
// [ shape ]
console.log(checkShape({}));
// [ not a shape ]

// ============================================
// PART 17: NESTED HIERARCHY
// ============================================

class Vehicle {}
class Car extends Vehicle {}
class ElectricCar extends Car {}

const tesla = new ElectricCar();

console.log(tesla instanceof ElectricCar);
// [ true ]
console.log(tesla instanceof Car);
// [ true ]
console.log(tesla instanceof Vehicle);
// [ true ]
console.log(tesla instanceof Object);
// [ true ]

// ============================================
// PART 18: MIXINS
// ============================================

const Serializable = {
  serialize() { return JSON.stringify(this); }
};

class User {}
Object.assign(User.prototype, Serializable);

const u = new User();
console.log(u instanceof User);
// [ true ]
console.log(typeof u.serialize);
// [ function ]

// ============================================
// PART 19: POLYMORPHISM
// ============================================

class Pay {
  process() { return 'generic'; }
}
class CardPay extends Pay {
  process() { return 'card'; }
}
class CashPay extends Pay {
  process() { return 'cash'; }
}

function pay(p) {
  if (!(p instanceof Pay)) {
    throw new TypeError('Expected a Pay');
  }
  return p.process();
}

console.log(pay(new CardPay()));
// [ card ]
console.log(pay(new CashPay()));
// [ cash ]

// ============================================
// PART 20: FULL SCRIPT
// ============================================

class Animal2 {}
class Dog3 extends Animal2 {}

const dog3 = new Dog3();

console.log(dog3 instanceof Dog3);
console.log(dog3 instanceof Animal2);
console.log(dog3 instanceof Object);
console.log(dog3 instanceof Array);

const arr2 = [1, 2, 3];
console.log(arr2 instanceof Array);
console.log(arr2 instanceof Object);

console.log([] instanceof Object);
console.log({} instanceof Object);
console.log("hello" instanceof String);
console.log(new String("hello") instanceof String);

Quick Reference

instanceof Basics

ExpressionResult
obj instanceof Constructortrue or false
null instanceof Xfalse
undefined instanceof Xfalse
primitive instanceof Xfalse
obj instanceof Objecttrue (unless Object.create(null))

typeof vs instanceof

Checktypeofinstanceof
Primitives
Functions"function"Function
Arrays"object"Array
null"object"false
Custom classes"object"

Built-in Checks

Valueinstanceof
[]Array, Object
{}Object
new Date()Date, Object
/re/RegExp, Object
function(){}Function, Object
new Map()Map, Object
new Set()Set, Object
Promise.resolve()Promise, Object

Hierarchy

Objectinstanceof
new ElectricCar()ElectricCar, Car, Vehicle, Object
new Dog()Dog, Animal, Object
new ValidationError()ValidationError, Error, Object

Alternatives

CheckUse forCross-realm
typeofPrimitives
instanceofClasses
Array.isArrayArrays
Object.prototype.toString.callEverything
.constructorQuick check❌ mutable

Best Practices

Do This:

// Check most specific first
if (x instanceof Dog) { ... }
else if (x instanceof Animal) { ... }       // ✅

// Use instanceof for error types
if (err instanceof ValidationError) { ... } // ✅

// Use Array.isArray for arrays
Array.isArray(value)                        // ✅

// Use typeof for primitives
typeof value === 'string'                   // ✅

// Validate class membership
if (!(x instanceof Shape)) {
  throw new TypeError('Expected Shape');
}                                            // ✅

// Use instanceof in type guards
function isDog(x) {
  return x instanceof Dog;
}                                            // ✅

// Check instanceof Object for "is an object"
value !== null && typeof value === 'object' // ✅ preferred

Don’t Do This:

// Don't use instanceof for primitives
"hi" instanceof String                      // ❌ false

// Don't rely on instanceof across realms
iframeArray instanceof Array                // ❌ false
Array.isArray(iframeArray)                  // ✅

// Don't use .constructor as a type check
x.constructor === Array                     // ❌ can be reassigned

// Don't check parent before child
if (x instanceof Animal) { ... }
else if (x instanceof Dog) { ... }          // ❌ Dog never reached

// Don't use instanceof with null
null instanceof Object                      // ✅ false, but be careful

// Don't confuse instanceof with typeof
typeof [] === 'array'                       // ❌ no such thing

// Don't forget Object.create(null)
const o = Object.create(null);
o instanceof Object                         // ❌ false

Common Pitfalls

PitfallProblemSolution
PrimitivesAlways falseUse typeof
Cross-realmfalse for real arraysUse Array.isArray
Parent before childChild branch unreachableCheck specific first
null instanceof XReturns false (never throws)Handle null separately
Object.create(null)Not an Object instanceCheck directly
.constructor mutableCan be overwrittenUse instanceof
Different realmDifferent constructorsUse Object.prototype.toString
Confusing with typeofBoth “check type”Use typeof for primitives

Real-World Examples

1. Basic Class Check

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

console.log(dog instanceof Dog);
// [ true ]

console.log(dog instanceof Animal);
// [ true ]

console.log(dog instanceof Object);
// [ true ]

console.log(dog instanceof Array);
// [ false ]

2. Built-in Types

const arr = [1, 2, 3];

console.log(arr instanceof Array);
// [ true ]

console.log(arr instanceof Object);
// [ true ]

console.log([] instanceof Object);
// [ true ]

console.log({} instanceof Object);
// [ true ]

3. Primitive vs Object

console.log("hello" instanceof String);
// [ false ]

console.log(new String("hello") instanceof String);
// [ true ]

4. Error Type Handling

class ValidationError extends Error {}

try {
  throw new ValidationError('Invalid input');
} catch (err) {
  if (err instanceof ValidationError) {
    console.log('Validation failed:', err.message);
  }
}
// [ Validation failed: Invalid input ]

5. Type Guard

function isDate(x) {
  return x instanceof Date;
}

console.log(isDate(new Date()));
// [ true ]

console.log(isDate('2024-01-01'));
// [ false ]

6. Multiple Constructors

const values = [
  new Map(),
  new Set(),
  [],
  {},
  new Date(),
  /regex/
];

for (const v of values) {
  if (v instanceof Map) console.log('Map');
  else if (v instanceof Set) console.log('Set');
  else if (v instanceof Array) console.log('Array');
  else if (v instanceof Date) console.log('Date');
  else if (v instanceof RegExp) console.log('RegExp');
  else console.log('Object');
}
// [ Map ]
// [ Set ]
// [ Array ]
// [ Object ]
// [ Date ]
// [ RegExp ]

7. Class Hierarchy Traversal

class A {}
class B extends A {}
class C extends B {}

const c = new C();

console.log(c instanceof C);
// [ true ]
console.log(c instanceof B);
// [ true ]
console.log(c instanceof A);
// [ true ]
console.log(c instanceof Object);
// [ true ]

8. Shape Area

class Shape {}
class Circle extends Shape {
  constructor(r) { super(); this.r = r; }
  area() { return Math.PI * this.r ** 2; }
}
class Square extends Shape {
  constructor(s) { super(); this.s = s; }
  area() { return this.s ** 2; }
}

function printArea(shape) {
  if (!(shape instanceof Shape)) {
    throw new TypeError('Expected a Shape');
  }
  console.log(shape.area().toFixed(2));
}

printArea(new Circle(5));
// [ 78.54 ]
printArea(new Square(4));
// [ 16.00 ]

9. instanceof vs typeof

console.log(typeof []);
// [ object ]

console.log([] instanceof Array);
// [ true ]

console.log(typeof null);
// [ object ]

console.log(null instanceof Object);
// [ false ]

10. Custom Symbol.hasInstance

class EvenNumber {
  static [Symbol.hasInstance](v) {
    return typeof v === 'number' && v % 2 === 0;
  }
}

console.log(2 instanceof EvenNumber);
// [ true ]
console.log(3 instanceof EvenNumber);
// [ false ]

11. User Input Validation

function isArray(value) {
  return value instanceof Array;
}

console.log(isArray([1, 2, 3]));
// [ true ]
console.log(isArray('hello'));
// [ false ]

12. Nested Inheritance Check

class Vehicle {}
class Car extends Vehicle {}
class ElectricCar extends Car {}

const tesla = new ElectricCar();

console.log(tesla instanceof ElectricCar);
// [ true ]
console.log(tesla instanceof Car);
// [ true ]
console.log(tesla instanceof Vehicle);
// [ true ]

13. Detect Custom Error

class AuthError extends Error {}
class NotFoundError extends Error {}

function handle(err) {
  if (err instanceof AuthError) return 'auth';
  if (err instanceof NotFoundError) return 'not found';
  if (err instanceof Error) return 'generic';
  return 'unknown';
}

console.log(handle(new AuthError()));
// [ auth ]
console.log(handle(new NotFoundError()));
// [ not found ]
console.log(handle(new Error()));
// [ generic ]

14. instanceof with Array.isArray

const data = [[1, 2], 'text', { a: 1 }, [3, 4]];

for (const item of data) {
  if (Array.isArray(item)) {
    console.log('Array with length', item.length);
  } else {
    console.log('Not an array');
  }
}
// [ Array with length 2 ]
// [ Not an array ]
// [ Not an array ]
// [ Array with length 2 ]

15. instanceof in a Validation Function

function assertDate(value) {
  if (!(value instanceof Date)) {
    throw new TypeError('Expected Date');
  }
  return value.toISOString();
}

console.log(assertDate(new Date('2024-01-15')));
// [ 2024-01-15T00:00:00.000Z ]

try {
  assertDate('2024-01-15');
} catch (e) {
  console.log(e.message);
}
// [ Expected Date ]

16. Polymorphic Dispatch

class Notification {}
class Email extends Notification {
  send() { return 'sending email'; }
}
class SMS extends Notification {
  send() { return 'sending SMS'; }
}

function sendAll(list) {
  for (const n of list) {
    if (n instanceof Notification) {
      console.log(n.send());
    }
  }
}

sendAll([new Email(), new SMS()]);
// [ sending email ]
// [ sending SMS ]

17. instanceof vs Duck Typing

const arrayLike = { length: 2, 0: 'a', 1: 'b' };

console.log(arrayLike instanceof Array);
// [ false ]

console.log(typeof arrayLike.length === 'number');
// [ true ]

18. Custom Collection

class Stack {
  constructor() { this.items = []; }
  push(x) { this.items.push(x); }
  pop() { return this.items.pop(); }
}

class Queue extends Stack {
  pop() { return this.items.shift(); }
}

const q = new Queue();
q.push(1);
q.push(2);

console.log(q instanceof Queue);
// [ true ]
console.log(q instanceof Stack);
// [ true ]
console.log(q.pop());
// [ 1 ]

19. instanceof in a Factory

class Logger {
  log(msg) { console.log(msg); }
}
class FileLogger extends Logger {
  log(msg) { /* write to file */ }
}

function createLogger(type) {
  const logger = type === 'file' ? new FileLogger() : new Logger();
  if (logger instanceof Logger) {
    return logger;
  }
  throw new Error('Invalid logger');
}

const l = createLogger('file');
console.log(l instanceof FileLogger);
// [ true ]

20. Full Script

class Animal {}
class Dog extends Animal {}

const dog = new Dog();

console.log(dog instanceof Dog);
console.log(dog instanceof Animal);
console.log(dog instanceof Object);
console.log(dog instanceof Array);

const arr = [1, 2, 3];
console.log(arr instanceof Array);
console.log(arr instanceof Object);

console.log([] instanceof Object);
console.log({} instanceof Object);
console.log("hello" instanceof String);
console.log(new String("hello") instanceof String);

Visual: instanceof Walks the Chain

┌──────────────────────────────────────────────┐
│           instanceof Dog                     │
│                                              │
│  Start at: dog                               │
│                                              │
│  dog.__proto__  ───►  Dog.prototype  ✅      │
│                                              │
│  Result: true                                │
│                                              │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│           instanceof Animal                  │
│                                              │
│  Start at: dog                               │
│                                              │
│  dog.__proto__  ───►  Dog.prototype   ✗      │
│         │                                    │
│         ▼                                    │
│  Dog.prototype.__proto__ ─► Animal.prototype ✅│
│                                              │
│  Result: true                                │
│                                              │
└──────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│           instanceof Array                   │
│                                              │
│  Start at: dog                               │
│                                              │
│  dog.__proto__         ──► Dog.prototype  ✗  │
│  Dog.prototype.__proto__ ─► Animal.prototype ✗│
│  Animal.prototype.__proto__ ─► Object.prototype ✗│
│  Object.prototype.__proto__ ─► null           │
│                                              │
│  Result: false                               │
│                                              │
└──────────────────────────────────────────────┘

Visual: typeof vs instanceof

┌──────────────────────────────────────────────┐
│  Value              typeof       instanceof  │
│  ──────────────────────────────────────────  │
│  42                 "number"     N/A         │
│  "hi"               "string"     N/A         │
│  true               "boolean"    N/A         │
│  null               "object" ❌  false       │
│  undefined          "undefined"  false       │
│  []                 "object" ❌  Array ✅    │
│  {}                 "object"     Object ✅   │
│  function(){}       "function"   Function ✅ │
│  new Date()         "object"     Date ✅     │
│  /regex/            "object"     RegExp ✅   │
│                                              │
└──────────────────────────────────────────────┘

Summary

ConceptSyntaxExample
Basic checkobj instanceof Cdog instanceof Dog
Inheriteddog instanceof Animaltrue if extends
Objectx instanceof ObjectMost objects true
Arrayx instanceof ArrayAlso use Array.isArray
nullnull instanceof XAlways false
Primitive"hi" instanceof Stringfalse
Error checkerr instanceof ErrorIn catch blocks
Customx instanceof MyClassAny class
CustomizeSymbol.hasInstanceOverride behavior

Key takeaways:

  • instanceof checks whether an object’s prototype chain includes the constructor’s prototype
  • It walks the entire chain — so a subclass instance matches all ancestor classes
  • It returns false for primitives — use typeof for those
  • It returns false for null and undefined — never throws
  • Order matters in if/else — check the most specific class first
  • Array.isArray() is preferred for arrays because it works across realms
  • .constructor is mutable — instanceof is more robust
  • Use instanceof with custom error classes for precise catch handling
  • Symbol.hasInstance lets you customize instanceof behavior
  • instanceof doesn’t cross realms (iframes, Workers) — use Object.prototype.toString or Array.isArray there
  • typeof null is "object" (a historical bug) but null instanceof Object is falseinstanceof is more correct here

Remember: instanceof answers “was this created by this class (or a subclass)?” It’s the right tool for class hierarchies, custom errors, and type guards. Use typeof for primitives, Array.isArray for arrays across realms, and instanceof for everything else. Watch out for the order of checks in if/else chains — specific first, general last. Master instanceof, and your type checks become reliable and expressive.


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!