W3docs

JavaScript instanceof

Оператор instanceof в JavaScript — мощный инструмент для проверки типов объектов и реализации полиморфизма в объектно-ориентированном коде.

Введение в оператор instanceof

Оператор instanceof в JavaScript — мощный инструмент для определения того, является ли object экземпляром конкретного класса или функции-конструктора. Он помогает разработчикам проверять тип object во время выполнения программы, упрощая проверку типов и эффективную реализацию полиморфизма. Оператор проверяет цепочку прототипов object относительно прототипа функции-конструктора и возвращает boolean-результат, указывающий, наследует ли object от этого прототипа.

Синтаксис и использование

Синтаксис оператора instanceof прост:

object instanceof Constructor
javascript— editable

Здесь object — это object, проверяемый относительно Constructor. Оператор возвращает true, если object является экземпляром Constructor или унаследован от него; в противном случае возвращается false.

Пример кода: базовое использование

Рассмотрим пример, в котором определяется класс Vehicle и создаётся его экземпляр:

javascript— editable

Продвинутые применения

Помимо базовой проверки типов, оператор instanceof играет ключевую роль в более сложных сценариях с наследованием и полиморфизмом. Рассмотрим сценарий с наследованием:

Пример кода: наследование

javascript— editable

Этот пример демонстрирует, как instanceof подтверждает, что myCar является не только экземпляром Car, но и экземпляром Vehicle, показывая способность оператора распознавать цепочку наследования.

Как instanceof обходит цепочку прототипов

instanceof не проверяет напрямую, какой конструктор создал object. Вместо этого он поднимается по цепочке прототипов object и задаёт вопрос: встречается ли Constructor.prototype где-либо в ней? Как только совпадение найдено, возвращается true; если достигнут конец цепочки (null) без совпадения, возвращается false.

javascript— editable

Из-за этого результат instanceof можно изменить, переназначив цепочку прототипов — проверка касается исключительно принадлежности к цепочке, а не конструктора, который выполнялся. Чтобы разобраться в самой цепочке, смотрите Прототипное наследование и Базовый синтаксис классов.

Настройка instanceof с помощью Symbol.hasInstance

Можно переопределить результат obj instanceof Constructor, определив статический метод [Symbol.hasInstance] на конструкторе. Если он присутствует, instanceof вызывает его с левым операндом и использует его boolean-результат, полностью игнорируя цепочку прототипов.

javascript— editable

Это полезно для утиной типизации — когда любой object, который «выглядит правильно», считается членом типа — без необходимости проходить через иерархию классов.

instanceof против typeof против constructor

Эти три инструмента отвечают на разные вопросы, и выбор неверного является распространённым источником ошибок.

  • typeof возвращает string с категорией примитивного типа. Отлично подходит для примитивов, но возвращает "object" почти для всего остального (array, null, даты, простые object), поэтому не может различать виды object.
  • instanceof проверяет принадлежность к цепочке прототипов и учитывает наследование — но не работает в разных контекстах выполнения (см. ниже) и не работает с примитивами.
  • obj.constructor указывает на функцию, создавшую object, но это просто перезаписываемое свойство, которое отражает только наиболее конкретный класс, а не всю цепочку.
javascript— editable

Встроенные конструкторы, использованные выше, рассмотрены в разделе Встроенные прототипы.

Особенность realm (iframe/window)

Каждый контекст браузера — каждый iframe или всплывающее окно — имеет собственный набор встроенных конструкторов и свои Array.prototype, Object.prototype и так далее. Array, созданный в iframe, является настоящим array, но он не наследует от Array.prototype вашего окна. В результате arrayFromIframe instanceof Array в родительском окне возвращает false, даже если значение является полноценным array. Это наиболее частая причина, по которой instanceof «лжёт».

Для значений, которые могут пересекать контексты выполнения, предпочтительнее использовать независимые от realm проверки, например Array.isArray(value).

Надёжные теги типов с Object.prototype.toString

Когда нужна надёжная, безопасная для разных realm проверка типа, которая также работает с примитивами, Object.prototype.toString возвращает строку внутреннего тега в форме [object Type]. Её нельзя обмануть переназначением прототипов, как в случае с constructor, и она работает в разных контекстах выполнения.

javascript— editable

Используйте его через .call(value), чтобы значение стало this. Класс даже может управлять собственным тегом с помощью свойства Symbol.toStringTag.

Лучшие практики и рекомендации

Несмотря на то что оператор instanceof незаменим, важно применять его обдуманно:

  • Зависимость от цепочки прототипов: оператор instanceof опирается на цепочку прототипов, поэтому изменения прототипа object могут влиять на результаты проверок instanceof.
  • Использование в полиморфизме: он особенно полезен в сценариях, где требуется полиморфное поведение, позволяя создавать гибкий код, способный обрабатывать object разных типов единообразно.
  • Проблемы с разными контекстами: будьте осторожны при использовании instanceof с object из разных JavaScript-контекстов (например, iframe или разных окон), поскольку каждый контекст имеет собственную уникальную цепочку прототипов.

Практический пример: полиморфизм

Вот как можно использовать instanceof для реализации полиморфного поведения:

javascript— editable

Заключение

Понимание и эффективное использование оператора instanceof критически важно для освоения объектно-ориентированных аспектов JavaScript. Он не только помогает проверять типы и обеспечивать корректность кода, но и позволяет писать более гибкий и поддерживаемый код с помощью полиморфизма. Грамотно интегрируя оператор instanceof в свою практику разработки, вы можете значительно повысить надёжность и масштабируемость ваших JavaScript-приложений.

Практика

Практика
Какие утверждения об операторе 'instanceof' в JavaScript верны?
Какие утверждения об операторе 'instanceof' в JavaScript верны?
Was this page helpful?