Дэвид Флэнаган - JavaScript. Подробное руководство, 6-е издание
- Название:JavaScript. Подробное руководство, 6-е издание
- Автор:
- Жанр:
- Издательство:Символ-Плюс
- Год:2012
- Город:СПб
- ISBN:978-5-93286-215-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дэвид Флэнаган - JavaScript. Подробное руководство, 6-е издание краткое содержание
Эта книга - одновременно и руководство программиста, и полноценный справочник по базовому языку JavaScript и клиентским прикладным интерфейсам, предоставляемым веб-броузерами.
JavaScript. Подробное руководство, 6-е издание - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В следующих подразделах описываются три приема определения класса произвольного объекта: оператор instanceof
, свойство constructor
и имя функции-конструктора. Однако ни один из этих приемов не дает полной гарантии, поэтому в разделе 9.5.4 мы обсудим прием грубого определения типа (duck-typing) - философии программирования, в которой центральное место отводится возможностям объекта (т. е. наличию тех или иных методов), а не его принадлежности к какому-либо классу.
9.5.1. Оператор instanceof
Оператор instanceof
был описан в разделе 4.9.4. Слева от оператора должен находиться объект, для которого выполняется проверка принадлежности к классу, а справа - имя функции-конструктора, представляющей класс. Выражение о instanceof с
возвращает true
, если объект о наследует с.prototype
. При этом наследование необязательно может быть непосредственным. Если о
наследует объект, который наследует объект, наследующий с.prototype
, выражение все равно вернет true
.
Как отмечалось выше в этой главе, конструкторы выступают в качестве наружной вывески классов, а фундаментальная идентификация классов проводится прототипами. Несмотря на то что в операторе instanceof
используется функция» конструктор, этот оператор в действительности проверяет прототип, наследуемый объектом, а не конструктор, с помощью которого он был создан.
Если необходимо проверить, входит ли некоторый определенный прототип в цепочку прототипов объекта без использования функции-конструктора, как промежуточного звена, можно воспользоваться методом isPrototypeOf()
. Например, ниже показано, как проверить принадлежность объекта г к классу range, определенному в примере 9.1:
range.methods.isPrototypeOf(г); // range.methods - объект-прототип.
Один из недостатков оператора instanceof
и метода isPrototypeOf()
состоит в том, что они не позволяют узнать класс объекта. Они лишь проверяют принадлежность объекта указанному классу. Еще более серьезные проблемы начинают возникать в клиентских сценариях JavaScript, когда веб-приложение использует несколько окон или фреймов. Каждое окно или фрейм имеет свой собственный контекст выполнения, и в каждом из них имеется свой глобальный объект со своим собственным набором функций-конструкторов. Два массива, созданные в двух разных фреймах, унаследуют идентичные, но разные объекты прототипов, и массив, созданный в одном фрейме, не будет распознаваться оператором instanceof как экземпляр конструктора Array()
в другом фрейме.
9.5.2. Свойство constructor
Другой способ определения класса объекта заключается в использовании свойства constructor. Поскольку конструкторы считаются именами классов, определение класса выполняется очень просто. Например:
function typeAndValue(x) {
if (х == null) return // Значения null и undefined не имеют конструкт.
switch(x.constructor) {
case Number: return "Number: " + x; // Работает с простыми типами
case String: return "String: " + x + ;
case Date: return "Date: ” + x; // Со встроенными типами
case RegExp: return "Regexp: " + x;
case Complex: return "Complex: + x; // И с пользовательскими типами
}
}
Обратите внимание, что выражения в этом примере, следующие за ключевыми словами case, являются функциями. Если бы мы использовали оператор typeof
или извлекали значение атрибута class
объекта, они были бы строками.
Для приема, основанного на использовании свойства constructor
, характерны те же проблемы, что и для приема на основе оператора instanceof
. Он не всегда будет работать при наличии нескольких контекстов выполнения (например, при наличии нескольких фреймов в окне броузера), совместно использующих общие значения. Каждый фрейм имеет собственный набор функций-конструкторов: конструктор Array в одном фрейме не будет считаться идентичным конструктору Array в другом фрейме.
Кроме того, язык JavaScript не требует, чтобы каждый объект имел свойство constructor
: это всего лишь соглашение, по которому по умолчанию объект-прототип создается для каждой функции, и очень просто по ошибке или преднамерение опустить свойство constructor
в прототипе. Например, первые два класса в этой главе (в примерах 9.1 и 9.2) были определены так, что их экземпляры не имеют свойства constructor
.
9.5.3. Имя конструктора
Основная проблема использования оператора instanceof
или свойства constructor
для определения класса объекта проявляется при наличии нескольких контекстов выполнения и, соответственно, при наличии нескольких копий функций-конструкторов. Эти функции могут быть совершенно идентичными, но разными объектами, как следствие, не равными друг другу.
Одно из возможных решений проблемы заключается в том, чтобы использовать в качестве идентификатора класса имя функции-конструктора вместо самой функции. Конструктор Array
в одном окне не будет равен конструктору Array
в другом окне, но их имена будут равны. Некоторые реализации JavaScript обеспечивают доступ к имени функции через нестандартное свойство name
объекта функции. Для реализаций, где свойство name
отсутствует, можно преобразовать функцию в строку и извлечь имя из нее. (Этот прием использовался в разделе 9.4, где демонстрировалось добавление в класс Function
метода getName()
.)
В примере 9.4 определяется функция type(),
возвращающая тип объекта в виде строки. Простые значения и функции она обрабатывает с помощью оператора typeof
. Для объектов она возвращает либо значение атрибута class
, либо имя конструктора. В своей работе функция type()
использует функцию classof()
из примера 6.4 и метод Function.getName()
из раздела 9.4. Для простоты реализация этой функции и метода включена в пример.
Пример 9.4. Функция type() для определения типа значения
/**
* Возвращает тип значения в виде строки:
* -Если о - null, возвращает "null", если о - NaN, возвращает "пап”.
* -Если typeof возвращает значение, отличное от "object", возвращает это значение.
* (Обратите внимание, что некоторые реализации идентифицируют объекты
* регулярных выражений как функции.)
* -Если значение атрибута class объекта о отличается от "Object",
Интервал:
Закладка: