Казахстан, Алматы, Гимназия им. Ахмета Байтурсынова №139, 2008 |
Клипы и ролики. Специальные возможности языка
Инструкция with и обсуждение областей видимости
Программистам часто приходится работать с многократно вложенными объектами (да еще, бывает, с длинными именами). Необходимость постоянно писать что-то наподобие
mySmartObject.favoriteField.theBestMethod(justTheSameArgument)
может изрядно раздражать. А поскольку мы уже умеем создавать вложенные клипы (читай - вложенные объекты), то пора бы познакомиться со способом сократить подобные записи. Способ этот - использование инструкции with .
Простейший пример
Инструкция with имеет синтаксис, похожий на синтаксис инструкции if. То есть сначала следует ключевое слово with , после него в круглых скобках - ссылка на объект, с полями которого мы собираемся работать; после закрывающей круглой скобки начинается блок (обрамленный фигурными скобками), внутри которого идентификаторы в первую очередь интерпретируются как имена полей заданного объекта. Вот простейший пример использования этой инструкции.
x = 100; trace("x = " + x); obj = {x: 10, y:15}; with (obj){ trace("with (obj): x = " + x); trace("with (obj): y = " + y); } trace("x = " + x);
На выходе получаем:
x = 100 with (obj): x = 10 with (obj): y = 15 x = 100
Пример посложнее
А теперь давайте рассмотрим более сложный пример.
a = {x: 10, y:15}; a.method = function(arg){ with(this){ trace("with(this): x = " + x); trace("with(this): eval(arg) = " + eval(arg)); } trace("eval(arg) = " + eval(arg)); } a.method("y");
Здесь инструкция with используется для того, чтобы избавиться от необходимости каждый раз писать this внутри метода некоторого объекта для обращения к его полям. Мы уже говорили об этой неприятной особенности языка ActionScript и о том, что чуть ли не половина ошибок при написании функций-методов происходит из-за того, что программисты написать this все-таки забывают (и какого-либо предупреждения от ActionScript 1.0 при компиляции не дождешься). Так вот, написав with (this) и обрамив относящимися к этой инструкции фигурными скобками все тело функции, вы избавитесь от подобных проблем. Не забудьте только, что для создания новых полей объекта with непригоден (подробнее об этом - чуть дальше).
Кроме того, из этого примера мы увидим, что использование eval замечательно сочетается с with : внутри with (this) надпись типа eval ("x") приведет к правильному результату (выдаче поля х ), а снаружи - нет. В самом деле, после запуска вышеприведенного кода на выполнение, получим в консоли следующий результат:
with(this): x = 10 with(this): eval(arg) = 15 eval(arg) =
Многоуровневые with
У инструкции with есть удобное свойство: внутри блока, относящегося к with , можно использовать еще одну инструкцию with . Вот пример работы с вложенными with :
a = {x: 10, y:15}; b = {x: 100, y: 150}; a.method = function(arg){ with(this){ trace("with(this): x = " + x); trace("with(this): eval(arg) = " + eval(arg)); with (b){ trace("with(b): x = " + x); trace("with(b): eval(arg) = " + eval(arg)); } this.b = {x: 1000, y: 1500}; // В качестве объекта, с которым работает следующий // оператор with будет взят объект this.b, потому что // мы находимся внутри блока, принадлежащего with(this) with (b){ trace("with(b): x = " + x); trace("with(b): eval(arg) = " + eval(arg)); } trace("with(this): x = " + x); trace("with(this): eval(arg) = " + eval(arg)); } trace("eval(arg) = " + eval(arg)); } a.method("y");
Выводит этот код вот что:
with(this): x = 10 with(this): eval(arg) = 15 with(b): x = 100 with(b): eval(arg) = 150 with(b): x = 1000 with(b): eval(arg) = 1500 with(this): x = 10 with(this): eval(arg) = 15 eval(arg) =
Интересно, что как только мы создали объект this.b, именно он стал в первую очередь восприниматься в качестве b (до тех пор, пока мы находились внутри блока with (this) ). В следующем параграфе мы обсудим вопрос старшинства областей видимости более детально.