Предложение with

Концепция цепочек областей видимости, используемая ActionScript, имеет не только положительные стороны. Так, код сценариев иногда получается уж очень громоздким. Особенно это характерно для фильмов, клипы которых обладают большой степенью вложенности. Также из-за того, что при вызове математических функций всякий раз приходится обращаться к объекту Math, формулы и алгебраические выражения зачастую выходят совершенно нечитабельными.

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

trace(Math.asin(Math.cos(0))/Math.Pl*180+ " градусов"); // Выводит:
// 90 градусов
trace(m.asin(m.cos(0)) /m.PI*180+ "градусов"); // Выводит:
// 90 градусов

Однако данный способ не является оптимальным. Гораздо лучше в тех случаях, когда в коде требуется произвести значительное число обращений к какому-то удаленному объекту, использовать специальное предложение with. Его синтаксис:

with (expression) statements,

где:
• expression – выражение, результатом вычисления которого является идентификатор объекта, к которому по умолчанию должны быть применены вызовы методов и свойств в блоке предложения with.


Чаще всего это просто имя объекта или строка, его хранящая;

• statements – блок с предложениями, в которых используется сокращенный синтаксис.

Пример:
with (Math) { // При вызове методов и свойств обращаемся к объекту Math
trace(asin(cos(0))/{PI*180+"градусов"); // Выводит: 90 градусов
}

Что же происходит, когда интерпретатор сталкивается с предложением with? При этом в конец используемой цепочки областей видимости (представляет собой список объектов, которые просматриваются при обращении к идентификатору) добавляется еще один элемент, указывающий на объект, прописанный в круглых скобках предложения with(). Например, если приведенный выше код введен на кадре основной временной диаграммы, то цепочка областей видимости для предложения в блоке with будет выглядеть следующим образом:

• объект Math. Он находится в приоритете;
• основная временная шкала (_root) (нужно учитывать, что она наследует свойства и методы прототипов конструкторов MovieClip и Object);
• объект Global.

Предложение with() можно использовать по отношению к совершенно любому объекту: начиная от экземпляров клипов или массивов и заканчивая прототипами классов и объектом Global.

Для кода, вводимого в блок предложения with, имеются и ограничения.


Так, вы не можете объявить в нем переменную или функцию. Вернее, это сделать можно, но набранный скрипт просто не будет связан с нужным объектом. Так, переменная не станет свойством удаленного клипа, а будет привязана к текущей временной диаграмме:

with (bigBall.smallBall) {
// Добавляем в цепочку областей видимости
// удаленный клип
var a:Number = 1; // Пытаемся сделать а свойством smallBall
}
trace(bigBall.smallBall.a); // Выводит: undefined
trace(a); // Выводит: 1 (переменная была сохранена на текущей
// временной диаграмме)

Чтобы удаленно создать свойство или метод, нужно использовать полный «адрес» объекта (лучше — вне предложения with):

bigBall.smallBall.а=1;

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

Опытные Flash-кодеры практически не используют предложения with, так как считается, что оно существенно замедляет скорость выполнения сценария. Доверяя авторитетам, мы все же проверим, справедливо ли игнорирование такого, в общем полезного элемента. Для этого мы сравним время, которое понадобится плейеру на то, чтобы просчитать сложное математическое выражение при прямом указании на объект Math и включении его в цепочку областей видимости посредством предложения with.


Чтобы результат был статистически корректным, проведем при помощи цикла 100 000 вычислений. Определить время, в течение которого выполнится код, можно, используя функцию getTimer(), возвращающую количество миллисекунд, прошедших с начала проигрывания фильма:

// Прямое указание на объект Math
for (var i = 0; i<100000; i++) {
Math.sin(Math.PI*Math.cos(0)*Math.tan(Math.PI/4)); {
}
trace(getTimer()); // Выводит: 545
// Использование предложения with
with (Math) {
for (var i = 0; i<100000; i++) {
sin(PI*cos(0)*tan(Pl/4));
}
}
trace(getTimer()); // Выводит: 2455

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

Во Flash 4 аналогом предложения with стандарта ЕСМА-262 было предложение tellTarget. Оно позволяло обращаться к методам и свойствам удаленного клипа, не прописывая полного пути к нему. Между tellTarget и with имеются два принципиальных отличия:

• Предложение with включает в цепочку областей видимости совершенно любой объект. Предложение tellTarget может указывать только на экземпляр клипа.

• В качестве параметра teliTargct принимает строку с адресом клипа, with —любое выражение, результат вычисления которого может быть преобразован в идентификатор объекта.

В настоящее время предложение tellTarget считается устаревшим, и его использование не рекомендовано. Однако иметь представление о нем надо, так как оно встречается в тексте многих выложенных в сети исходников.

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

Статьи из раздела Action Script на эту тему:
Блок предложений
Обработка исключительных ситуаций. Предложения try-catch-finally, throw и класс Error
Предложение return
Предложения var и function
Предложения выражений и пустые предложения

Вернуться в раздел: Action Script / 6. Предложения