Московский физико-технический институт
Опубликован: 23.12.2005 | Доступ: свободный | Студентов: 2869 / 253 | Оценка: 4.61 / 4.44 | Длительность: 27:18:00
ISBN: 978-5-9556-0051-2
Лекция 2:

Базовые понятия Action Script

Конвертация типов

Несмотря на то что ссылки во Флэш МХ не типизированы (то есть одна и та же ссылка может указывать на объекты разных типов), работа с типами здесь поддержана неплохо. Мы уже говорили о том, как определить тип объекта. Кроме того, есть средства явного и неявного преобразования типов. Сначала поговорим о неявном преобразовании. Мы рассмотрим здесь наиболее важные случаи неявного преобразования типов. Некоторые дополнительные сведения (например, преобразования строк при сравнении) будут рассмотрены в параграфе, посвященном выражениям.

При сложении строчка старше всех

При использовании оператора "плюс" для сцепления (конкатенации) строк, строка имеет преимущество над всеми остальными типами. Это значит, что в случае нужды части выражения других типов будут преобразованы в строки. Посмотрите на следующий пример.

trace((5 > 7) + 10 + " Строка ");
trace(10 + " Строка " + (5 > 7));
trace(10 - " Строка " - (5 > 7));

Запустив его на выполнение, мы увидим в консоли вот что:

10 Строка
10 Строка false
NaN

В первых двух операторах trace операнды, к которым прибавлялась строка, преобразовались в строки. Только в первом случае значение выражения (5 > 7) + 10 было вычислено сначала. При этом тоже было произведено преобразование типов: если в выражении встречаются Boolean и Number, и семантика выражения при этом подразумевает арифметические операции, то осуществляется преобразование к Number. При этом true преобразовывается в 1, а false - в 0. (Если же выполняются логические операции, то, напротив, Number преобразуется к Boolean: любое ненулевое число означает true, а ноль - false ).

Таким образом, в первом вызове trace в нашем примере сначала было вычислено значение логического выражения, получилось false, что преобразовалось в ноль и в сумме с десяткой дало опять-таки десять. А уж потом эта десятка была состыкована со строкой. Во втором же вызове trace логическое выражение прибавлялось к строке, поэтому мы и получили там false в явном виде.

Наконец, в третьем вызове trace выражение содержало операцию "минус", что не подразумевает преобразования к строке. Поэтому пришлось преобразовывать строку к числу, что дало в результате NaN.

Явное преобразование типов

Иногда бывает нужно произвести явное преобразование типа. Для этого существуют четыре глобальных функции: Number(), String(), Boolean() и Object(). (Между прочим, это не просто функции, это также и конструкторы соответствующих типов. Но пока что мы их будем употреблять в качестве обыкновенных функций.) В качестве аргумента в эти функции подставляется преобразуемый объект, возвращается (примитивный) объект нужного типа. Ни к каким более типам (в том числе пользовательским) преобразование невозможно. Впрочем, поскольку проверка типа во Флэше не производится, преобразование к пользовательским типам совершенно не нужно. Все необходимые вещи могут быть сделаны без преобразования. Наконец, семантика Флэш МХ такова, что говорить о пользовательских типах вообще не очень корректно (хотя классы пользователь может создать какие угодно).

Но не будем отвлекаться и рассмотрим подробнее явные преобразования. Преобразование к типу String совсем простое - оно сводится к вызову метода toString у нужного объекта. Преобразование к Boolean также вполне тривиально для всех типов, не являющихся строчкой. А именно, все, что не есть 0, Number.NaN, null или undefined - это true. А вот строчки преобразуются к Boolean транзитом через Number, то есть Boolean(str) - это то же самое, что Boolean(Number(str)). И теперь мы естественным образом переходим к самому интересному - к тому, как осуществляются преобразования из String в Number. (С преобразованиями в Number остальных типов все понятно: Boolean преобразуется в 0 или 1 соответственно, а прочие типы в Number.NaN ). Итак, чтобы описать преобразование из String в Number, удобно будет сначала рассмотреть более подробно работу глобальных функций parseInt и parseFloat. Несмотря на свои названия, обе эти функции способны извлекать из строки как целые числа, так и дробные. Но при этом числа в экспоненциальной записи правильно прочесть можно только при использовании parseFloat. Зато parseInt корректно обрабатывает 16-ричную запись с префиксом , восьмеричную с префиксом 0, а также запись в любой системе счисления от 2 до 36, если основание системы счисления явно указано во втором аргументе этой функции. Надо заметить, что каждая из этих функций пытается воспринять максимальное количество символов строки (начиная слева) как число. Это число она выдает в качестве результата своей работы, а все "лишние" символы в правой части строки игнорируются. И только когда в качестве числа не удается воспринять ни одного символа в строке (начиная слева), выдается Number.NaN. Так вот, функция Number при работе с аргументом строкового типа представляет собой своего рода гибрид этих двух функций - с той, однако, существенной разницей, что Number.NaN выдается, если в преобразуемой строке остался хотя бы один лишний символ (даже если это пробел). То есть функция Number пробует интерпретировать строку как число всеми возможными способами - и как целое в десятичной, восьмеричной или шестнадцатеричной системе счисления, и как число в записи с фиксированной или плавающей точкой - и лишь потерпев неудачу во всех попытках, выдает Number.NaN.

// Создаем примитивную строку и проверяем ее на примитивность
a = "Примитивная строка";
   // Выводим значение строки
trace("a = " + a);
   // Пытаемся создать новое поле
a.r = 5;
   // Создать новое поле не удается - строка read-only
trace("a.r = " + a.r);
   // Проверяем на примитивность еще одним способом
trace("(a instanceof String) = " + (a instanceof String) + "\n");
   // Теперь конвертируем этот объект и проделываем
   // все те же операции еще раз
a = Object(a);
trace("a = " + a);
a.r = 5;
trace("a.r = " + a.r);
trace("(a instanceof String) = " + (a instanceof String));

На выходе имеем:

a = Примитивная строка
a.r =
(a instanceof String) = false
a = Примитивная строка
a.r = 5
(a instanceof String) = true

Эти результаты наилучшим образом подкрепляют наше утверждение о том, что функция Object() просто делает из read-only -объекта объект обыкновенный. (Конечно, с исходным read-only -объектом ничего не происходит. Создается новый объект, уже не примитивный. Фактически, вместо Object(a) мы в нашем примере могли бы писать и new Object(a) с абсолютно тем же результатом.)