Диагностика, ремонт и защита

         

Область видимости


Область видимости является вторым следствием вложенности объектов. Область видимости означает что-то вроде "контекста", в том смысле, "что именно можно увидеть/понять с разных точек/мест". Возвращаясь опять к метафоре с младенцем, младенец может видеть "внутри" своей матери (с фонариком), но не может видеть видеть то, что видит мама. В ActionScript вы можете автоматически делать ссылку на область видимости объекта, в первую очередь, ActionScript будет искать свойства в собственной области видимости объекта.

Из всех характеристик контейнеров, которые нас больше всего интересуют, наиболее полезной является не их картонность, а их "контейнеробильность" (эдакое вот словечко в стиле Дж. Буша). В контейнеры можно помещать все, что угодно, включая другие контейнеры. Изнутри контейнера, можно видеть только те предметы, которые находятся в нем, но никак не те, что снаружи. И, хотя вы можете видеть другие контейнеры в вашей области видимости, заглянуть внутрь них вам не удастся. Рассмотрим несложный пример. Давайте создадим еще один объект personA: personA= { name : "Ann", favs : { site1 : "flash.com", test1 : function(){ trace (this.site1) }, test2 : function(){ trace (this.name ) } }, test3: function(){ trace (this.name ) }, test4: function(){ trace (this.site1) } }; personA.favs.test1(); // flash.com personA.favs.test2(); // null (ребеной не может видеть родителя) personA.test3(); // Ann personA.test4(); // null (родитель не может видеть внутри ребенка)

В этом примере, ключевое слово this означает "контейнер, вызвавший эту функцию", что по счастью означает именно тот контейнер, который мы пытаемся увидеть внутри. На данном этапе, совершенно необязательно разбираться в том, как это работает, достаточно на простом языке описать, что будет на выходе каждого свойства test. test1: Свойство, называемое site1 в контейнере personA.favs. // которое имеет значение "flash.com" test2: Свойство, называемое name в контейнере personA.favs. // нет такого свойства в personA.favs test3: Свойство, называемое name в контейнере personA. // которое имеет значение "Ann" test4: Свойство, называемое site1 в контейнере personA. // нет такого свойства в personA

Интересно, что будет, если мы изменим test4 следующим образом: test4: function(){return this.favs.site1;} // Обратите внимание на '.favs.'

Отлично, работает. Что же на выходе? test4: Свойство, называемое site1, в контейнере, называемом favs, который находится в данном контейнере. // ? попробуйте найти значение, используя новый test4 код...


Что происходит, когда мы определяем свойство, используя ключевое слово var? Создаётся локальное свойство. "Локальный" - значит "действующий только в пределах границ данного объекта" или, если хотите, "в пределах границ данного контейнера". Что-то типа "первого парня на деревне", которые рождаются и умирают в пределах одной маленькой деревеньки и никогда никуда из нее не выбираются. Вот пример локального свойства, определённого в классе: A = function() { var temp = 5; this.x = temp; } trace(A.temp); // не здесь

Где именно действует свойство temp в данном примере? Его действие распространяется на часть функции A, являющуюся "объектом активации" (иногда также используется термин "конструктор функции"). Означает ли это, что мы найдём его с помощью выражения A.temp? Нет. Потому что в этом примере мы его только определяем, целиком объект активации остаётся не вызванным пока не вызвано выражение A(). Означает ли это, что он станет доступным после того, как вызвано выражение A? Нет. Потому что, после того, как вызвано A, он не принимается в расчёт. Вообще, каждый раз, когда вызывается функция, создаётся такой вот объект активации, и каждый раз, когда функция заканчивает своё действие, этот объект активации перестаёт приниматься в расчёт (хотя во Flash 5 из памяти он обычно не удаляется и не исчезает. Ай-яй-яй!). Итак, temp действует в пределах границ этого временного объекта. Однако, из-за того, что у этого объекта активации нет имени и он просто "находится неподалёку" во время действия функции, никакая другая часть программы не имеет к нему доступа (если только вы не вызовете функцию из функции и та вторая функция не увидит его с помощью своего свойства this). Когда он заканчивает своё действие, его локальные свойства не сохраняются.

Многие думают, что "в ActionScript всё, что ни есть - всё объект". Это не совсем так. Кое-что может и не быть объектом или, как это ни странно, может быть более, чем одним объектом. Вышеприведённая функция, это два объекта (вообще-то, строго говоря, целых три, но об этом позже). Существуют объекты-ссылки, называемые A, которые ведут себя, как любые другие объекты. Вы можете добавлять к ним свойства, например A.temp и эти свойства будут вставлены в объект A. У вас также есть блок инструкций, которые составляют функцию. Это и будет вторым объектом - объектом активации, который создаётся каждый раз, когда вызывается функция.

При использовании первого объекта A существует ряд ограничений. Главная задача этого объекта - дать имя блоку функций, чтобы его можно было вызвать. После этого можете использовать его именное пространство для хранения информации о самой функции. Такой информацией может быть, например, имя класса объекта (которое может понадобиться для исправления ошибок), или счётчик, который следит за количеством экземпляров, вызванных с помощью объекта. Такие свойства никак не повлияют на работу функции. В последующих экземплярах от них не останется и следа.

Второй объект, объект активации, производит самопостроение в процессе создания экземпляра. Он бывает совершенно необходим. У него свои границы действия, а его собственное ключевое слово this присваивается контейнеру, в котором он может создавать или изменять свойства. И это только часть его возможностей в создании экземпляра, самый распространённый, но вовсе не самый значимый случай его использования. У нас будет возможность убедиться в этом, когда мы начнём разбираться с прототипами.



  



Содержание раздела