Skip to main content

The instanceof operator

The instanceof operator in JavaScript checks whether an object is an instance of a particular class or constructor function. Technically it determines whether Constructor.prototype is present in that object's prototype chain.

Theory

TL;DR

  • Syntax: object instanceof Constructor, the result is always true or false.
  • The operator walks up the object's prototype chain looking for Constructor.prototype.
  • It respects inheritance: rex instanceof Animal is true even when rex was created from class Dog extends Animal.
  • Almost everything descends from Object, so obj instanceof Object is usually true.
  • It does not work with primitives: 123 instanceof Number is false.
  • Different contexts (iframe, worker) have their own constructors, so Array.isArray() is more reliable for arrays.

Quick example

javascript
class User {} const user = new User(); console.log(user instanceof User); // true console.log(user instanceof Object); // true, because every object inherits from Object

Here user is an instance of User and at the same time an instance of Object, because User inherits from Object.

How it works under the hood

instanceof does not look at the "type" of a value, it walks the prototype chain:

  1. it takes object.__proto__ (that is, Object.getPrototypeOf(object));
  2. it compares that with Constructor.prototype;
  3. if there is no match, it moves one level up: object.__proto__.__proto__ and so on;
  4. if a match is found anywhere in the chain it returns true, and if the chain ends at null it returns false.
javascript
function Animal() {} const dog = new Animal(); // The check: console.log(dog instanceof Animal); // true // The same thing by hand: console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true

A class can override this behaviour through the well-known symbol Symbol.hasInstance: when the constructor defines it, instanceof calls that method instead of doing the default prototype walk.

Inheritance and built-in types

The operator climbs the whole inheritance tree, not just one level:

javascript
class Animal {} class Dog extends Animal {} const rex = new Dog(); console.log(rex instanceof Dog); // true console.log(rex instanceof Animal); // true console.log(rex instanceof Object); // true console.log(rex instanceof Array); // false

The chain here is Dog -> Animal -> Object.

It works the same way with plain constructor functions:

javascript
function Car() {} function Bike() {} const roadster = new Car(); console.log(roadster instanceof Car); // true console.log(roadster instanceof Bike); // false

And with built-in types, arrays for example:

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

Every array is an object, so arr instanceof Object is true as well.

Primitives and wrapper objects

instanceof does not work with primitives at all:

javascript
console.log(123 instanceof Number); // false console.log('hello' instanceof String); // false

The reason is simple: 123 and 'hello' are primitives, not objects, so there is no prototype chain of their own to walk.

Wrapper objects, on the other hand, are matched normally:

javascript
const n = new Number(123); console.log(n instanceof Number); // true const s = new String('hi'); console.log(s instanceof String); // true

In real code the wrappers new Number and new String are almost never used, primitives are the better choice.

When instanceof fails: other contexts

If an object arrives from another context (an iframe, a separate window, a worker), the check can unexpectedly return false, because that context has its own Array constructor with its own prototype:

javascript
iframe.contentWindow.Array !== window.Array;

So the value really is an array, yet value instanceof Array returns false. For that case there is a separate check that works across contexts:

javascript
Array.isArray(value);

Summary table

PropertyValue
What it checksWhether Constructor.prototype is in the object's prototype chain
What it returnstrue / false
What it works withObjects, not primitives
What it compares againstConstructor.prototype
Does it respect inheritanceYes
Suitable for arrays, classes, functionsYes

A final example to lock it in:

javascript
class Person {} class Developer extends Person {} const tim = new Developer(); console.log(tim instanceof Developer); // true console.log(tim instanceof Person); // true console.log(tim instanceof Object); // true console.log(tim instanceof Array); // false

Common mistakes

  • Expecting true for primitives. 'hello' instanceof String is false; to check a primitive you need typeof.
  • Confusing instanceof with typeof. typeof looks at the type of the value, instanceof at the prototype chain; for any plain object typeof always returns 'object'.
  • Checking arrays with instanceof Array in code that receives data from an iframe or a worker. The right tool there is Array.isArray().
  • Forgetting that almost everything is an instance of Object. A value instanceof Object check proves almost nothing beyond "this is not a primitive".
  • Using instanceof on null or undefined. The result is always false and no error is thrown, so the bug is easy to miss.
  • Reassigning a constructor's prototype after objects were created. Existing instances still point at the previous prototype, so instanceof becomes false for them.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.