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 alwaystrueorfalse. - The operator walks up the object's prototype chain looking for
Constructor.prototype. - It respects inheritance:
rex instanceof Animalistrueeven whenrexwas created fromclass Dog extends Animal. - Almost everything descends from
Object, soobj instanceof Objectis usuallytrue. - It does not work with primitives:
123 instanceof Numberisfalse. - Different contexts (iframe, worker) have their own constructors, so
Array.isArray()is more reliable for arrays.
Quick example
class User {}
const user = new User();
console.log(user instanceof User); // true
console.log(user instanceof Object); // true, because every object inherits from ObjectHere 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:
- it takes
object.__proto__(that is,Object.getPrototypeOf(object)); - it compares that with
Constructor.prototype; - if there is no match, it moves one level up:
object.__proto__.__proto__and so on; - if a match is found anywhere in the chain it returns
true, and if the chain ends atnullit returnsfalse.
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); // trueA 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:
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); // falseThe chain here is Dog -> Animal -> Object.
It works the same way with plain constructor functions:
function Car() {}
function Bike() {}
const roadster = new Car();
console.log(roadster instanceof Car); // true
console.log(roadster instanceof Bike); // falseAnd with built-in types, arrays for example:
const arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // trueEvery array is an object, so arr instanceof Object is true as well.
Primitives and wrapper objects
instanceof does not work with primitives at all:
console.log(123 instanceof Number); // false
console.log('hello' instanceof String); // falseThe 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:
const n = new Number(123);
console.log(n instanceof Number); // true
const s = new String('hi');
console.log(s instanceof String); // trueIn 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:
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:
Array.isArray(value);Summary table
| Property | Value |
|---|---|
| What it checks | Whether Constructor.prototype is in the object's prototype chain |
| What it returns | true / false |
| What it works with | Objects, not primitives |
| What it compares against | Constructor.prototype |
| Does it respect inheritance | Yes |
| Suitable for arrays, classes, functions | Yes |
A final example to lock it in:
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); // falseCommon mistakes
- Expecting
truefor primitives.'hello' instanceof Stringisfalse; to check a primitive you needtypeof. - Confusing
instanceofwithtypeof.typeoflooks at the type of the value,instanceofat the prototype chain; for any plain objecttypeofalways returns'object'. - Checking arrays with
instanceof Arrayin code that receives data from an iframe or a worker. The right tool there isArray.isArray(). - Forgetting that almost everything is an instance of
Object. Avalue instanceof Objectcheck proves almost nothing beyond "this is not a primitive". - Using
instanceofonnullorundefined. The result is alwaysfalseand no error is thrown, so the bug is easy to miss. - Reassigning a constructor's
prototypeafter objects were created. Existing instances still point at the previous prototype, soinstanceofbecomesfalsefor them.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.