Есть ли переменные в ActionScript?

Между понятиями «свойство» и «переменная» нет заметной разницы. И первое, и второе обозначают именованный контейнер для хранения данных — и на уровне реализации языка трудно найти различие между ними. Свойство является структурным элементом объекта, а переменная существует сама по себе — вот и вся разница. Однако в ActionScript стирается даже это отличие между свойствами и переменными. Так, размещая код на кадре основной временной шкалы, мы можем создать переменную с использованием ключевого слова var. Но если нам необходимо прочитать значение этой переменной из вложенного на _root клипа, то обратиться к ней мы должны как к свойству, применив оператор «.» или «[]». Переменные остаются переменными только в рамках «родной» временной шкалы. Вне ее они уже свойства определенного объекта класса MovieClip. To же самое можно сказать про локальные переменные функций: их вполне можно считать свойствами ее объекта активации (и, как будет показано в главе 4, они таковыми и являются).

Учитывая сказанное выше, правильнее было бы назвать эту главу не «Переменные», а «Свойства». Впрочем, практически все, что было изложено ранее, в равной степени справедливо как для переменных, так и для свойств.


Например, присваивание свойству другого свойства с составным зна-чением будет означать передачу ссылки на объект данных, а не его копирование.

Расположение кода на кадрах клипов делает сценарии фильмов Flash чрезвычайно гибкими. Однако это вносит и значительную путаницу во многие вопросы языка. Например, нужно ли использовать var, если переменная клипа создается удаленно? Ответ; нет, так как при этом она рассматривается как свойство. Нужно ли ключевое слово var, если объявляется глобальная переменная? Ответ: нет, так как она есть просто свойство объекта Global. Вообще оператор точки и var не совместимы: такое сочетание вызывает ошибку.

var _root.myVar=0; // Ошибка: переменная не может быть свойством

В ЕСМА-262 с каждым исполнимым кодом связана особая служебная структура, называемая объектом переменных (variable object). Свойства этого объекта имеют такие же имена, как и определенные в коде переменные и функции. Значениями же этих свойств являются объекты данных, с которыми при помощи операции присваивания связываются соответствующие переменные. При необходимости получить доступ к некоторой переменной считывается значение созданного на основании ее определения свойства объекта переменных.


Понятие «объект переменных» вводится для того, чтобы стала возможной инкапсуляция исполнимого кода и реализация концепции цепочек областей видимости.

В ActionScript роль объекта переменных основного кода выполняет клип, на кадре которого код расположен. С одной стороны, это хорошо, так как способствует упрощению языка. Например, чтобы обратиться к какому-то свойству или методу клипа из кода, расположенного на нем, совсем не обязательно использовать имя клипа, Достаточно набрать просто имя свойства:

trace(_х); // Выводит: 0
trace(_root._x) // Выводит: 0

С другой стороны, создание на основании определения переменной свойства клипа означает, что различия между понятиями «переменная» и «свойство» нивелируются. Интересные особенности возникают при обращении к свойству клипа из расположенного на нем кода. Так, если мы попытаемся получить к нему доступ, не используя имя клипа и оператор точки, а набрав только имя, то на его наличие будет просмотрена связанная с исполнимым кодом цепочка областей видимости. Это означает, что в данном случае идентификатор рассматривается как имя переменной. Если же к свойству мы пытаемся обратиться, используя имя клипа и оператор точки, то просматривается связанная с клипом цепочка прототипов (идентификатор интерпретируется как свойство).


Так как три звена (сам клип, прототип конструктора MovieClip, прототип конструктора Object) у цепочки наследования клипа и цепочки областей видимости расположенного на нем кода совпадают, то в подавляющем большинстве случаев не возникает никаких различий от того, как происходит обращение к свойству клипа или переменной кода. Однако если переменная является глобальной, то обратиться к ней как к свойству клипа невозможно. Это связано с тем, что объект Global имеется в любой цепочке областей видимости, однако в цепочку наследования клипов он не входит:

_global.per="Привет"; // Создаем глобальную переменную
trace(per); // Выводит: Привет (per воспринимается как переменная)
trace(_root.per); // Выводит: undefined (per воспринимается как свойство)

Из-за того, что переменные и функции одновременно являются свойствами и методами клипа-носителя кода, путаются понятия цепочки областей видимости и цепочки прототипов. Формально в цепочку областей видимости кода, расположенного на кадре клипа, входят сам клип и объект Global. Но из-за того, что при обращении к свойству клипа на его наличие просматриваются еще и прототипы конструкторов MovieClip и Object, количество объектов, фактически входящих в цепочку областей видимости, увеличивается до четырех. Конечно, между свойствами, получаемыми из цепочки наследования клипа, и «настоящими» переменными, принадлежащими к полноценным объектам цепочки областей видимости исполнимого кода, имеются определенные отличия. Так, наследуемое свойство клипа переопределено не может быть, а собственное свойство клипа — с легкостью. Однако в подавляющем большинстве случаев свойства, принадлежащие к прототипа мконструкторов MovieClip и Object, и свойства самого клипа и объекта Global ведут себя при обращении из кода к идентификатору абсолютно идентично. Поэтому для простоты мы будем считать, что цепочка областей видимости кода клипа выглядит следующим образом: сам клип, прототип конструктора MovieClip, прототип конструктора Object, объект Global. На самом же деле, как вы уже знаете, структура цепочки областей видимости кода клипа куда проще. Ее видимое удлинение возникает из-за того, что при обращении к свойству клипа на его наличие проверяется также характерная для него цепочка прототипов.

Если бы для кода, расположенного на кадре клипа, создавался специальный объект переменных, а не использовался с этой целью сам клип, то понятия «переменная» и «свойство» было бы легко различить, и не возникало бы такой путаницы с цепочками областей видимости и цепочками прототипов. Будем надеяться, что в следующих версиях Flash ситуация в этом отношении изменится.

Имеется только одно серьезное отличие между переменными и свойствами. Переменную можно строго типизировать, а свойство — нет. Впрочем, эта особенность существует лишь до компиляции. В транслированном коде обнаружить различие между свойством клипа и переменной расположенного на нем кода невозможно.

Проанализировав приведенные факты, мы можем сделать следующее заключение: в ActionScript в принципе нет переменных, а есть переменные-свойства. Такой странный симбиоз возник из-за применения не слишком удачной концепции языка программирования. Согласитесь, что не так много общего между браузером и программой векторной анимации, чтобы использовать для них один стандарт скриптового языка (а ЕСМА-262 — это стандарт именно Web-скриптов). Пожалуй, определенной стройности ActionScript можно было бы добиться, отказавшись от жесткой привязки сценариев к временной шкале — но это радикально усложнит кодирование, поэтому разработчики вряд ли на это пойдут (но первый шаг разработчиками к этому уже сделан — в область видимости кода методов внешних классов входят только объект, вызвавший метод, и объект Global).

Автор этой книги считает запутанность понятий переменная-свойство одним из главных недостатков ActionScript. При всем желании невозможно описать эту головоломку какой-то стройной схемой. Да и лучше этого не делать — вывод, к которому вы придете, приведен в предыдущем абзаце. Действуйте интуитивно — это самый верный подход во многих вопросах программирования во Flash.

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Action Script на эту тему:
Локальные переменные функций
Особенности операции присваивания
Особенности типизации переменных
Создание переменных
Удаление переменных

Вернуться в раздел: Action Script / 3. Переменные