Базовые понятия Action Script
Откуда взялся ActionScript
Ответ на вопрос, вынесенный в заголовок этого параграфа, прост и сложен одновременно. Разумеется, язык ActionScript был разработан фирмой Macromedia, выпускающей Флэш. Однако разработан не на пустом месте, а на основе стандарта ECMA-262.
Сначала скажем, как расшифровывается аббревиатура ECMA: это European Computer Manufacturers Association (Европейская ассоциация производителей компьютеров). Эта ассоциация (разумеется, не она одна) занимается стандартами в области вычислительной техники.
ActionScript, как и другой известный язык JavaScript, базируется на стандарте ECMA-262. (Фактически, стандарт был сделан на основе начальных версий JavaScript, а не наоборот, а вот ActionScript уже был сделан на основе стандарта. Конечно, само существование стандарта на развитие языка JavaScript также повлияло). Стандарт разработан специально для скриптовых языков, поэтому не специфицирует полностью все встроенные объекты. То есть для JavaScript встроенными объектами являются браузер и его окна, для ActionScript - клипы, кнопки, текстовые поля и компоненты Flash. Сам стандарт ECMA-262 имеет несколько версий, самая свежая, (к которой и имеет непосредственное отношение ActionScript 1.0) - это версия 3. (Вообще-то готовится версия 4, и на основе ее бета-версии уже сделан язык ActionScript 2.0, используемый во Флэш МХ 2004. Но его мы не будем рассматривать в этой книге). Надо отметить, что стандарт в ActionScript поддержан все-таки не полностью. Не реализована обработка исключений и регулярных выражений, ограничена функциональность оператора eval (об этом см. в лекции 3). Тем не менее, ActionScript соответствует стандарту в значительной степени.
Если вы хотите ознакомиться со стандартом ECMAScript, он же ECMA-262, вы можете это сделать на сайте ECMA (http://www.ecma-international.org, конкретный адрес http://www.ecma-international.org/publications/standards/Ecma-262.htm ), или на сайте Mozilla в разделе, посвященном языку JavaScript (http://www.mozilla.org/js/language/ , здесь вы сможете найти стандарт в формате Microsoft Word).
Еще раз скажем, что последней версией стандарта является третья; вторая версия в свое время была утверждена в качестве стандарта ISO/IEC 16262, однако в настоящее время ISO уже отозвала этот стандарт.
Также отметим, что большинство нововведений, которые были сделаны в третьей версии стандарта (такие, как регулярные выражения, обработка исключений и т.п.), не вошли в ActionScript.
Почему вам будет легко освоить ActionScript
Вашу работу на ActionScript значительно облегчит то, что большинство простых конструкций, которые сработают на С++ или Java, сработают и на ActionScript. Так что, если перед вами стоит задача написать кусочек кода в 50 строк - попробуйте написать код, который бы заработал и в C++ и в Java (учтите, что объявлять переменные заранее не нужно). С довольно большой вероятностью вам удастся заставить вашу программу вести себя так, как вы того хотите. Существенный минус такого способа (помимо того, что он не годится для программ более 100 строк) состоит в том, что остается ощущение некачественно сделанной работы. Профессионал-программист обычно не только хочет, чтобы его программа работала, он еще и хочет понимать, почему именно она работает. Так что давайте вникать в детали - начиная с самых базовых вещей. Но при этом мы все же будем считать, что вы понимаете общий смысл кода на ActionScript - даже если некоторые применяемые там вещи мы еще не обсуждали. Для профессионала С++ или Java такое предположение будет, без сомнения, верным. Если же вы, по каким-либо причинам, используете эту книгу, впервые изучая язык с С-подобным синтаксисом - запаситесь еще одним учебником, в котором этот синтаксис рассмотрен более подробно. (В любом случае вам не помешает какая-нибудь толстая книжка по Флэш-дизайну из тех, что указаны в списке литературы.)
Но прежде чем мы погрузимся в детали, упомянем пару удивительных и непривычных вещей, с которыми нам придется столкнуться. Первая из них такова: точки с запятой после операторов во Флэше ставить необязательно! (Мы не будем пользоваться этой "свободой", она от лукавого.) Вторая удивительная вещь (впрочем, в настоящее время она уже не так удивительна) - это полная поддержка Unicode, в том числе - для идентификаторов языка. То есть, если вам хочется, то ваши классы, объекты, их поля и методы вы можете называть по-русски и русскими буквами.
Типы данных (примитивные и объектные)
Ну что ж, начнем наше путешествие вглубь ActionScript.
Изучая любой язык программирования, желательно в первую очередь разобраться, какими типами данных он оперирует. Несмотря на то что ActionScript (в отличие от ActionScript 2) не имеет проверки типов, сами типы данных (в случае надобности, автоматически преобразовывающиеся друг в друга) в нем существуют. Сначала мы рассмотрим эти типы, выражения, которые можно из объектов этих типов составлять и переменные, в которые результаты выполнения выражений можно записывать.
В С++ провести разделение между типами можно, задав вопрос, применим ли к объектам данного типа оператор "точка". Храниться же могут как объекты, так и данные примитивных типов, в одних и тех же областях памяти: в стеке, в статической памяти, в куче. В Java разделение по применимости оператора "точка" тоже присутствует, однако есть и еще одна важная вещь. Объекты хранятся в отдельном месте, переменная объектного типа не содержит объект, это лишь ссылка на него. Примитивные же типы хранятся прямо в недрах объектов, так что переменная примитивного типа представляет собой именно хранилище соответствующих данных, а не ссылку.
Во Флэше все обстоит по-другому. Не так, как в С++, но и не так, как в Java. То есть оператор "точка" применим также и к примитивным типам. А где же хранятся реальные данные примитивных типов? Можно заглянуть в стандарт и все узнать... но нас такая информация волновать не должна. Потому что есть весьма удобная точка зрения на примитивные типы, дающая ответ на все практические вопросы.
Примитивные типы
Итак, мы можем сказать, что примитивный тип - это то же самое, что объектный, но доступный только для чтения ( read-only ). У примитивного объекта могут быть свои поля (свойства) и методы, однако эти поля не могут изменяться и все методы примитивных типов не меняют сам объект.
Другой способ говорить об этом - это так называемая "упаковка", когда при обращении к функциям примитивного типа из него тут же создается соответствующий временный объект; но результат тот же: примитивный тип виден нам как объект, который мы не в состоянии изменять.
Какая же из точек зрения правильная? Согласно стандарту ECMAScript, первая ближе к истине. То есть имеются типы данных, не обладающие свойствами типа Object: дополнением к нему полей и методов. И вообще их содержимое не может быть изменено. С точки зрения С++ или Java это, тем не менее, объекты, поскольку собственными полями и методами они обладают. Вот мы и называем эти примитивные типы данных read-only -объектами. А какая же точка зрения удобнее? Как проще рассуждать: говоря о read-only -объектах, или об упаковке? На наш взгляд, опять-таки удобнее первая точка зрения. Но если вам нравится считать, будто число - это обычное число, и только при применении к нему оператора " ." оно преобразовывается в некоторый временный read-only -объект, пожалуйста, рассуждайте так. Ибо средствами самого Флэш МХ никакой разницы между этими двумя точками зрения мы обнаружить не сможем.
Общеупотребительных примитивных типов не так много: это String, Number и Boolean. (Эти же типы могут быть не только примитивными, но и объектными - говоря иначе, объекты String, Number и Boolean не обязаны быть read-only ). Как создать объект примитивного типа? (Да, не очень-то это хорошо звучит - "объект примитивного типа " - но в данном случае все так и есть. Примитивный во Флэш значит - read-only ). Сделать это можно либо напрямую указав значение в тексте программы, либо вычислив какое-либо выражение, значение которого имеет тип String, Number или Boolean. Естественное исключение из указанного выше правила - вызов методов каких-либо объектов. Эти методы могут вернуть ссылку на объектный String, Number или Boolean. Однако, если вы вызываете методы встроенных объектов Флэш - можете не беспокоиться, во всех случаях, когда возвращаемый тип бывает примитивным, возвращается именно примитивное значение. Еще одно исключение - использование оператора eval, с которым мы познакомимся позднее. Вот примеры выражений, дающих в результате примитивные типы:
"строка", 1е-12, 5<4, false + "10", 1. + "1"
А теперь, чтобы вы убедились, что с данными примитивных типов все-таки можно обращаться как с объектами, посмотрите на такой код:
a = (5 < 4).toString(); // В переменную записывается слово false trace("a.length = " + a.length); trace("9+6..toString() = " + 9+6..toString()); trace("строка, набранная строчными буквами".toUpperCase());
Этот код выводит в консоль
a.length = 5 9+6..toString() = 96 СТРОКА, НАБРАННАЯ СТРОЧНЫМИ БУКВАМИ
Итак, мы видим, что и булевское, и числовое, и строчное выражение допускают вызов какого-либо метода для примитивного объекта, являющегося значением выражения. Главное - позаботиться о синтаксисе. Если выражение брать в круглые скобки - никаких проблем не возникнет. А вот в случае числового выражения во втором операторе вывода в консоль нам пришлось поставить две точки перед именем метода (хотя можно было выкрутиться и при помощи скобок). Если бы мы поставили одну точку после цифры 6, это означало бы, что за ней следует некоторое количество (возможно, ноль) десятичных знаков, но никак не сразу имя метода. Поэтому пришлось ставить две точки, и это уже воспринимается однозначно. Обратите также внимание, что в том же самом выражении к преобразованной в строку шестерке была прибавлена числовая девятка. Тем не менее, она тоже была преобразована в строку. При неявном преобразовании типов во Флэше преобразование в строку имеет приоритет - оно всегда применяется, если один из операндов строковый и полученное выражение будет иметь смысл очевидных операций со строками. Впрочем, о преобразованиях типов мы поговорим далее.
Для порядка проверим, что все, что сказано в этом подпараграфе про скобки, также работает. В самом деле, запустив код
trace(4+(7).toString()); trace(4+(7));
мы на выходе получим
47 11
так что синтаксис со скобками работает, как ожидалось.