# Проверка класса: "instanceof" Оператор `instanceof` позволяет проверить, какому классу принадлежит объект, с учетом прототипного наследования. [cut] ## Алгоритм работы instanceof [#ref-instanceof] Вызов `obj instanceof Constructor` возвращает `true`, если объект принадлежит классу `Constructor` или классу, наследующему от него. Пример использования: ```js run function Rabbit() {} *!* // создаём объект */!* var rabbit = new Rabbit(); // проверяем -- этот объект создан Rabbit? *!* alert( rabbit instanceof Rabbit ); // true, верно */!* ``` Массив `arr` принадлежит классу `Array`, но также и является объектом `Object`. Это верно, так как массивы наследуют от объектов: ```js run var arr = []; alert( arr instanceof Array ); // true alert( arr instanceof Object ); // true ``` Как это часто бывает в JavaScript, здесь есть ряд тонкостей. Проверка происходит через сравнение прототипов, поэтому в некоторых ситуациях может даже ошибаться! **Алгоритм проверки `obj instanceof Constructor`:** 1. Получить `obj.__proto__` 2. Сравнить `obj.__proto__` с `Constructor.prototype` 3. Если не совпадает, тогда заменить `obj` на `obj.__proto__` и повторить проверку на шаге 2 до тех пор, пока либо не найдется совпадение (результат `true`), либо цепочка прототипов не закончится (результат `false`). В проверке `rabbit instanceof Rabbit` совпадение происходит на первом же шаге этого алгоритма, так как: `rabbit.__proto__ == Rabbit.prototype`. А если рассмотреть `arr instanceof Object`, то совпадение будет найдено на следующем шаге, так как `arr.__proto__.__proto__ == Object.prototype`. Забавно, что сама функция-конструктор не участвует в процессе проверки! Важна только цепочка прототипов для проверяемого объекта. Это может приводить к забавному результату и даже ошибкам в проверке при изменении `prototype`, например: ```js run // Создаём объект rabbit, как обычно function Rabbit() {} var rabbit = new Rabbit(); // изменили prototype... Rabbit.prototype = {}; // ...instanceof перестал работать! *!* alert( rabbit instanceof Rabbit ); // false */!* ``` Стоит ли говорить, что это один из доводов для того, чтобы никогда не менять `prototype`? Так сказать, во избежание. ```warn header="Не друзья: `instanceof` и фреймы" Оператор `instanceof` не срабатывает, когда значение приходит из другого окна или фрейма. Например, массив, который создан в ифрейме и передан родительскому окну -- будет массивом *в том ифрейме*, но не в родительском окне. Проверка `instanceof Array` в родительском окне вернёт `false`. Вообще, у каждого окна и фрейма -- своя иерархия объектов и свой `window` . Как правило, эта проблема возникает со встроенными объектами, в этом случае используется проверка внутреннего свойства `[[Class]]`, которое подробнее описано в главе . ``` ## Итого - Оператор `obj instanceof Func` проверяет тот факт, что `obj` является результатом вызова `new Func`. Он учитывает цепочку `__proto__`, поэтому наследование поддерживается. - Оператор `instanceof` не сможет проверить тип значения, если объект создан в одном окне/фрейме, а проверяется в другом. Это потому, что в каждом окне -- своя иерархия объектов. Для точной проверки типов встроенных объектов можно использовать свойство `[[Class]]`. Оператор `instanceof` особенно востребован в случаях, когда мы работаем с иерархиями классов. Это наилучший способ проверить принадлежность тому или иному классу с учётом наследования.