Suggest an editImprove this articleRefine the answer for “Checking a class instance”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**The main way is the `instanceof` operator: it checks whether `Class.prototype` is in the object's prototype chain, so it correctly accounts for inheritance.** ```javascript class Animal {} class Dog extends Animal {} const dog = new Dog(); console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true ``` The alternatives (`obj.constructor === Class`, `Object.getPrototypeOf(obj) === Class.prototype`) are narrower: the first breaks if `prototype.constructor` was reassigned, the second only sees the direct prototype and never walks up the chain. **Key point:** `instanceof` walks up the prototype chain and supports inheritance, but it can return `false` for an object created in another context (iframe, Worker), so for arrays `Array.isArray()` is safer.Shown above the full answer for quick recall.Answer (EN)Image**`instanceof` is the main way to check that an object is an instance of a class: the operator looks for `Class.prototype` in the object's prototype chain.** That is exactly why it works with inheritance and with built-in classes, and why its limits come down to cases where the prototype chain was changed by hand or the object came from another JavaScript context. ## Theory ### TL;DR - `obj instanceof Class` returns `true` if `Class.prototype` appears in the prototype chain of `obj`. - The operator walks up the chain, so it supports inheritance: `dog instanceof Animal` is `true`. - `obj.constructor === Class` checks the constructor, but breaks if `prototype.constructor` was reassigned. - `Object.getPrototypeOf(obj) === Class.prototype` only works for a direct instance and ignores inheritance. - With built-in classes (`Array`, `Date`, `Error`, `Map`) `instanceof` behaves the same way, because they are built on prototypes too. - Across contexts (iframe, Worker) the constructors differ, so `instanceof` may return `false`; for arrays use `Array.isArray()`. ### Quick example ```javascript class User {} const u = new User(); console.log(u instanceof User); // true ``` ### How `instanceof` works under the hood The expression `obj instanceof Class` is roughly equivalent to this code: ```javascript let proto = Object.getPrototypeOf(obj); while (proto) { if (proto === Class.prototype) return true; proto = Object.getPrototypeOf(proto); } return false; ``` So `instanceof` simply checks for the presence of `Class.prototype` in the `__proto__` chain. There is no "type magic" here: it is an ordinary walk over a linked list of prototypes. ### Inheritance and the prototype chain Because the operator walks up the chain, it sees every ancestor of the class: ```javascript class Animal {} class Dog extends Animal {} const dog = new Dog(); console.log(dog instanceof Dog); // true console.log(dog instanceof Animal); // true, inheritance works console.log(dog instanceof Object); // true, every object inherits from Object ``` Deeper inheritance behaves the same way: ```javascript class A {} class B extends A {} class C extends B {} const c = new C(); console.log(c instanceof A); // true console.log(c instanceof B); // true console.log(c instanceof C); // true ``` The prototype chain here looks like this: ```javascript c -> C.prototype -> B.prototype -> A.prototype -> Object.prototype -> null ``` `instanceof` climbs this chain step by step until it finds a match or reaches `null`. ### Alternatives: `constructor`, `getPrototypeOf` and a static method You can check whether the object's constructor matches the class: ```javascript class User {} const u = new User(); console.log(u.constructor === User); // true ``` But this approach breaks in two cases: if the object was created through `Object.create()` with a different prototype, or if someone changed `prototype.constructor`. Here is an example where both checks still agree, because the prototype chain is intact: ```javascript const fake = Object.create(User.prototype); console.log(fake.constructor === User); // true console.log(fake instanceof User); // true ``` > Both approaches work as long as the prototype chain is not broken. The third option is a direct prototype comparison: ```javascript class User {} const u = new User(); console.log(Object.getPrototypeOf(u) === User.prototype); // true ``` It works only for a direct instance: if inheritance is involved, the method will not climb further up the chain, unlike `instanceof`. In large codebases the check is often moved into a static method on the class itself, so the logic lives in one place: ```javascript class User { static isUser(obj) { return obj instanceof User; } } const u = new User(); console.log(User.isUser(u)); // true ``` ### Built-in classes and different contexts With built-in classes the operator behaves exactly the same, since they are built on prototypes too: ```javascript console.log([] instanceof Array); // true console.log([] instanceof Object); // true console.log(new Date() instanceof Date); // true console.log(new Date() instanceof Object); // true ``` The problem shows up when the object was created in another "reality", for example in another iframe or in a Worker. Those have their own globals, so `Array` or `Object` is a different constructor and the check may return `false`: ```javascript // arr came from another iframe console.log(arr instanceof window.Array); // false ``` The fix for arrays is the built-in check that does not depend on the context: ```javascript Array.isArray(arr); // safe even across contexts ``` ### Summary table | Approach | Example | What it checks | Supports inheritance | Note | | --- | --- | --- | --- | --- | | `instanceof` | `obj instanceof Class` | The `__proto__` chain | Yes | Reliable default | | `constructor` | `obj.constructor === Class` | The object's constructor | Partly | Breaks with a modified `prototype` | | `Object.getPrototypeOf` | `Object.getPrototypeOf(obj) === Class.prototype` | The direct prototype | No | Only for the exact class | | Static method | `Class.isInstance(obj)` | Any logic you want | Yes | Convenient in large projects | ### Common mistakes - **Treating `instanceof` as a type check.** It is a prototype chain check, not a check of a value's type. For primitives it always returns `false`: `'text' instanceof String` is `false`. - **Using `instanceof Array` for data from a foreign context.** Constructors differ between an iframe and a Worker, so `Array.isArray()` is required there. - **Relying on `obj.constructor` when the class may have reassigned `prototype`.** After a manual `Class.prototype = {}` the `constructor` property is lost and the check gives a wrong result. - **Confusing `Object.getPrototypeOf(obj) === Class.prototype` with `instanceof`.** The former does not see ancestors, so an instance of a subclass fails that check. - **Forgetting that `instanceof` does not work with `null` and `undefined`.** Such values have no prototype, so the result is always `false`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.