JavaScript. Подробное руководство, 6-е издание, стр. 113

<b>range.methods.isPrototypeOf(г); // range.methods - объект-прототип.</b>

Один из недостатков оператора

<b>instanceof</b>
и метода
<b>isPrototypeOf()</b>
состоит в том, что они не позволяют узнать класс объекта. Они лишь проверяют принадлежность объекта указанному классу. Еще более серьезные проблемы начинают возникать в клиентских сценариях JavaScript, когда веб-приложение использует несколько окон или фреймов. Каждое окно или фрейм имеет свой собственный контекст выполнения, и в каждом из них имеется свой глобальный объект со своим собственным набором функций-конструкторов. Два массива, созданные в двух разных фреймах, унаследуют идентичные, но разные объекты прототипов, и массив, созданный в одном фрейме, не будет распознаваться оператором instanceof как экземпляр конструктора
<b>Array()</b>
в другом фрейме.

9.5.2. Свойство constructor

Другой способ определения класса объекта заключается в использовании свойства constructor. Поскольку конструкторы считаются именами классов, определение класса выполняется очень просто. Например:

<b>function typeAndValue(x) {</b>

<b>  if (х == null) return // Значения null и undefined не имеют конструкт.</b>

<b>  switch(x.constructor) {</b>

<b>    case Number: return &quot;Number: &quot; + x; // Работает с простыми типами</b>

<b>    case String: return &quot;String: &quot; + x +  ;</b>

<b>    case Date: return &quot;Date: ” + x; // Со встроенными типами</b>

<b>    case RegExp: return &quot;Regexp: &quot; + x;</b>

<b>    case Complex: return &quot;Complex: + x; // И с пользовательскими типами</b>

<b>  }</b>

<b>}</b>

Обратите внимание, что выражения в этом примере, следующие за ключевыми словами case, являются функциями. Если бы мы использовали оператор

<b>typeof</b>
или извлекали значение атрибута
<b>class</b>
объекта, они были бы строками.

Для приема, основанного на использовании свойства

<b>constructor</b>
, характерны те же проблемы, что и для приема на основе оператора
<b>instanceof</b>
. Он не всегда будет работать при наличии нескольких контекстов выполнения (например, при наличии нескольких фреймов в окне броузера), совместно использующих общие значения. Каждый фрейм имеет собственный набор функций-конструкторов: конструктор Array в одном фрейме не будет считаться идентичным конструктору Array в другом фрейме.

Кроме того, язык JavaScript не требует, чтобы каждый объект имел свойство

<b>constructor</b>
: это всего лишь соглашение, по которому по умолчанию объект-прототип создается для каждой функции, и очень просто по ошибке или преднамерение опустить свойство
<b>constructor</b>
в прототипе. Например, первые два класса в этой главе (в примерах 9.1 и 9.2) были определены так, что их экземпляры не имеют свойства
<b>constructor</b>
.

9.5.3. Имя конструктора

Основная проблема использования оператора

<b>instanceof</b>
или свойства
<b>constructor</b>
для определения класса объекта проявляется при наличии нескольких контекстов выполнения и, соответственно, при наличии нескольких копий функций-конструкторов. Эти функции могут быть совершенно идентичными, но разными объектами, как следствие, не равными друг другу.

Одно из возможных решений проблемы заключается в том, чтобы использовать в качестве идентификатора класса имя функции-конструктора вместо самой функции. Конструктор

<b>Array</b>
в одном окне не будет равен конструктору
<b>Array</b>
в другом окне, но их имена будут равны. Некоторые реализации JavaScript обеспечивают доступ к имени функции через нестандартное свойство
<b>name</b>
объекта функции. Для реализаций, где свойство
<b>name</b>
отсутствует, можно преобразовать функцию в строку и извлечь имя из нее. (Этот прием использовался в разделе 9.4, где демонстрировалось добавление в класс
<b>Function</b>
метода
<b>getName()</b>
.)

В примере 9.4 определяется функция

<b>type(),</b>
возвращающая тип объекта в виде строки. Простые значения и функции она обрабатывает с помощью оператора
<b>typeof</b>
. Для объектов она возвращает либо значение атрибута
<b>class</b>
, либо имя конструктора. В своей работе функция
<b>type()</b>
использует функцию
<b>classof()</b>
из примера 6.4 и метод
<b>Function.getName()</b>
из раздела 9.4. Для простоты реализация этой функции и метода включена в пример.

Пример 9.4. Функция type() для определения типа значения

<b>/**</b>

<b> * Возвращает тип значения в виде строки:</b>

<b> *  -Если о - null, возвращает &quot;null&quot;, если о - NaN, возвращает &quot;пап”.</b>

<b> *  -Если typeof возвращает значение, отличное от &quot;object&quot;, возвращает это значение.</b>

<b> *   (Обратите внимание, что некоторые реализации идентифицируют объекты</b>

<b> *   регулярных выражений как функции.)</b>

<b> *  -Если значение атрибута class объекта о отличается от &quot;Object&quot;,</b>

<b> *   возвращает это значение.</b>

<b> *  -Если о имеет свойство constructor, а конструктор имеет имя, возвращает</b>

<b> *   имя конструктора.</b>

<b> *  -Иначе просто возвращает &quot;Object&quot;.</b>

<b>**/</b>

<b>function type(o) {</b>