Skip to main content

instanceof та прототипи

оператор instanceof напряму пов'язаний із прототипами і буквально перевіряє:

"Чи знаходиться prototype конструктора десь у ланцюжку прототипів об'єкта?"

Розберемо по кроках.


Коротко

Синтаксис:

javascript
obj instanceof Constructor

Повертає true, якщо у ланцюжку прототипів об'єкта obj присутній об'єкт Constructor.prototype.

Інакше повертає false.


Приклад

javascript
function User() {} const tim = new User(); console.log(tim instanceof User); // true console.log(tim instanceof Object); // true console.log(tim instanceof Array); // false

Під капотом instanceof перевіряє:

javascript
tim.__proto__ === User.prototype або tim.__proto__.__proto__ === User.prototype і так далі, поки не дійде до null

Як це працює "під капотом"

javascript
function instanceOf(obj, Constructor) { let proto = Object.getPrototypeOf(obj); // починаємо з [[Prototype]] while (proto) { if (proto === Constructor.prototype) return true; // знайшли збіг proto = Object.getPrototypeOf(proto); // рухаємось вгору } return false; // дійшли до null - не знайшли }

Саме так instanceof проходить ланцюжок прототипів, поки не знайде збіг.


Візуально

javascript
function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype); const rex = new Dog();

Ланцюжок:

javascript
rex → Dog.prototypeAnimal.prototypeObject.prototypenull

Перевірки:

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

Тому що всі ці прототипи зустрічаються в ланцюжку rex.__proto__.


Приклад із класами (той самий принцип)

javascript
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

Синтаксис інший, але під капотом - той самий ланцюжок прототипів.


Приклад, де instanceof поверне false

javascript
function User() {} const tim = new User(); Object.setPrototypeOf(tim, null); console.log(tim instanceof User); // false (ланцюжок обірвався)

Якщо об'єкт позбавлений прототипу або ланцюжок не містить User.prototype, оператор поверне false.


Особливість із різними контекстами (наприклад, iframes)

javascript
const arr = []; console.log(arr instanceof Array); // true // але в іншому вікні/iframe: console.log(arr instanceof window.top.Array); // false

Тому що у кожного контексту (frame, realm) свій Array.prototype, і instanceof порівнює саме об'єкт за посиланням, а не за назвою.


Альтернатива: obj.constructor

javascript
const user = new User(); console.log(user.constructor === User); // true

Але це ненадійно: властивість constructor можна перевизначити:

javascript
user.constructor = null; console.log(user instanceof User); // все ще true

Тому instanceof - безпечніший спосіб.


Підсумок

ПеревіркаЩо робитьВикористовує
obj instanceof ConstructorПеревіряє, чи є Constructor.prototype у ланцюжку прототипів об'єкта[[Prototype]]
Повертаєtrue або false
Надійніше, ніж obj.constructorТак
Працює з класамиТак
Чутливий до контексту (iframe)Так

Візуальна схема

javascript
obj __proto__ → Constructor.prototype __proto__ → Object.prototype null

Якщо Constructor.prototype зустрічається на цьому шляху, instanceof поверне true.


В одній фразі:

instanceof перевіряє, чи входить prototype конструктора в ланцюжок прототипів об'єкта, рухаючись вгору по __proto__, поки не знайде збіг або null.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.