PDA

Просмотр полной версии : Возникло недопонимание интервальных функций


orcpochta
30.05.2008, 13:07
Пример-программа из библии по AS2.0, где генерируются мерцающие буквы в случайном месте сцены. В среде авторских работ создается динамическое текстовое поле, куда монтируется несколько букв определенного шрифта для дальнейшего программного доступа к ним.
Далее пишется следующий код:

function displayLetter():Void {

// Create a random integer to yield one of the indices from the
// aLetters array.
var nRandomIndex:Number = Math.ceil(Math.random() * aLetters.length) - 1;

// Create random numbers to use for the x and y coordinates of the
// letter TextField.
var nRandomX:Number = Math.random() * 550;
var nRandomY:Number = Math.random() * 400;

// Get the next available depth;
var nDepth:Number = this.getNextHighestDepth();

// Create a new TextField object at the random x and y coordinates.
this.createTextField("tLetter" + nDepth, nDepth, nRandomX, nRandomY, 0, 0);

// Assign a reference to a variable to make it more convenient to
// work with the TextField.
var tLetter:TextField = this["tLetter" + nDepth];

// Set the autoSize and text properties so the random letter
// displays.
tLetter.autoSize = "left";
tLetter.text = aLetters[nRandomIndex];

// Set a custom property called fadeDirection that determines
// the increment by which the alpha will change. And set the
// alpha to 0 initially.
tLetter.fadeDirection = 5;
tLetter._alpha = 0;

// Tell Flash to embed the font for the TextField.
tLetter.embedFonts = true;

// Create a TextFormat object that tells Flash to use the
// Verdana font and set the size to 15.
var tfFormatter:TextFormat = new TextFormat();
tfFormatter.font = "Verdana";
tfFormatter.size = 15;

// Assign the TextFormat to the TextField.
tLetter.setTextFormat(tfFormatter);

// Set an interval at which the letter will fade in and out.
tLetter.nInterval = setInterval(this, "alphaFade", 10, tLetter);
}

function alphaFade(tLetter:TextField):Void {

// Increment the letter TextField's alpha.
tLetter._alpha += tLetter.fadeDirection;

// Check to see if the letter has faded in completely. If so
// set the fadeDirection property to -5 so that the TextField
// starts to fade out. Otherwise, if the letter has faded out
// completely...
if(tLetter.fadeDirection > 0 && tLetter._alpha >= 100) {
tLetter.fadeDirection = -5;
}
else if(tLetter.fadeDirection < 0 && tLetter._alpha <= 0) {
// ... clear the interval and remove the TextField.
clearInterval(tLetter.nInterval);
tLetter.removeTextField();
}

// Make sure to update the screen.
updateAfterEvent();
}

// Create the array of letters.
var aLetters:Array = ["a", "b", "c", "d", "e", "f"];

// Set the interval at which a new letter should be displayed.
var nDisplayInterval:Number = setInterval(this, "displayLetter", 1);


Бегло пробежался по коду и стал его воспроизводить на свой манер и тут возникла проблема - белое поле и ничего не происходит. Первым делом потрейсил, все ли функции запускаются? - запускаются все. Далее стал искать, проблему в инициализации текстового поля - нашел, что
var nDepth:Number = this.getNextHighestDepth();
trace(nDepth);
- выдает undefined.
Стал искать серьезные отличии в кодах и увидел, что у меня запуск интервальных функций инициализирован не
tLetter.nInterval = setInterval(this, "alphaFade", 10, tLetter);
var nDisplayInterval:Number = setInterval(this, "displayLetter", 1);
, а
tLetter.nInterval = setInterval(alphaFade, 10, tLetter);
var nDisplayInterval:Number = setInterval(displayLetter, 1);
- к чему я, собственно, изучая эту книгу и привык.
Т.е. в книге говорится, что синтаксис запуска функций: setInterval(functionName, interval, params );
объектных методов: setInterval(objectName, "objectMethod", interval, params);

Посмотрел мануал, действительно, есть синтаксис setInterval(this, "functionName", interval, params); - я так понимаю, что он идентичен синтаксису setInterval(functionName, interval, params );, но почему же тогда при синтаксисе через this все работает, а при другом нет?
Объясните разницу, если она есть, плиз.

Извините, что так много букв...)))

Волгоградец
30.05.2008, 13:36
Все упирается в область видимости имен. Если в функции displayLetter () есть ссылка с помощью this, то в методе setInterval () эта ссылка даст другое значение. Когда используешь такую сигнатуру:
setInterval(objectName, "objectMethod", interval, params);
То сам задаешь область видимости функции.

orcpochta
30.05.2008, 13:58
Извините, ничего не понял..((

Волгоградец
30.05.2008, 14:25
http://www.flasher.ru/forum/showthread.php?t=104635

Alex_beginner
30.05.2008, 14:55
Если Вы проанализируете работу вот этого кода то поймете почему.
myObject:Object = {};
myObject.method = function(par:String):Void
{
trace(par);
};
setInterval(myObject, "method", 100, "Привет orcpochta");

orcpochta
30.05.2008, 15:02
http://www.flasher.ru/forum/showthread.php?t=104635

я примерно понял, но осталось уяснить какую роль играет this в самом первом вызове интервальной функции var nDisplayInterval:Number = setInterval(this, "displayLetter", 1); - чем this там является?

Если Вы проанализируете работу вот этого кода то поймете почему.
myObject:Object = {};
myObject.method = function(par:String):Void
{
trace(par);
};
setInterval(myObject, "method", 100, "Привет orcpochta");

забыли var в объявлении myObject..))
опять же тут все ясно: создается объект, ему присваивается метод, который затем и вызывается в интервале - но это никак меня не приблизило к пониманию моего вопроса..))

Alex_beginner
30.05.2008, 15:15
забыли var в объявлении myObject..))
Виноват, исправляюсь! Сильно торопился Вам помочь, что даже ненаписал var.:)

Волгоградец
30.05.2008, 15:45
Если здесь
var nDisplayInterval:Number = setInterval(this, "displayLetter", 1);
опустить слово this, то получится вот что:
вот эта строчка
this.createTextField("tLetter" + nDepth, nDepth, nRandomX, nRandomY, 0, 0);
не будет работать, т.к. в этом случае слово this будет относиться к методу setInterval (), т.е. для компилятора строчка будет выглядеть как
setInterval.createTextField()
А т.к. у setInterval нет такого метода, то и появляется ошибка.

orcpochta
01.06.2008, 17:18
Спасибо! Разобрался..))

etc
09.06.2008, 15:25
Если здесь
var nDisplayInterval:Number = setInterval(this, "displayLetter", 1);
опустить слово this, то получится вот что:
вот эта строчка
this.createTextField("tLetter" + nDepth, nDepth, nRandomX, nRandomY, 0, 0);
не будет работать, т.к. в этом случае слово this будет относиться к методу setInterval (), т.е. для компилятора строчка будет выглядеть как
setInterval.createTextField()
А т.к. у setInterval нет такого метода, то и появляется ошибка.
Неправда.

Волгоградец
09.06.2008, 16:32
Как неправда???! Просветите, пожалуйста.

etc
09.06.2008, 16:37
Как неправда???! Просветите, пожалуйста.

Узнайте, что такое «область видимости».

Волгоградец
09.06.2008, 16:55
__etc, при всем моем уважении, но помощь у вас неважная.
Цепочка областей видимости — это список ActionScript-объектов. Flash Player ищет идентификатор, начиная с последнего элемента в цепочке областей видимости, и продолжает подниматься по цепочке, пока не найдет его.
В случае с setinterval () this в качестве первого параметра - это объект _root, при условии что код находится на главной временной диаграмме?

etc
09.06.2008, 16:59
this — это ссылка на самого себя. При передачи области видимости метод будет выполнен в ней. Если область не указана, то метод будет выполнен в анонимной области видимости.

p.S. В помошники я и не записывался.

Волгоградец
09.06.2008, 17:18
Предполагаю, что анонимная область видимости - это объект Object или _root, другими словами.

etc
09.06.2008, 17:35
Нет, у этой области видимости вообще нет this, это не _root и не Object.

Волгоградец
09.06.2008, 17:53
__etc, если не секрет, откуда вы это узнали - этого нет ни в хэлпе, ни в других букварях и даже Гугле!!! Я вот впервые услышал про анонимную область видимости и до сих пор не понимаю ее смысл.

wvxvw
09.06.2008, 18:31
в этом можно легко убедиться =)
setTimeout.someVar = 'foo';
var i:Number = setTimeout(someFunc, 100);
function someFunc():Void {
trace(this); //undefined
trace(this.someVar); //undefined // this не указывает на setTimeout
trace(arguments.callee.someVar); //bar // arguments.callee указывает на someFunc
trace(arguments.caller.someVar); //undefined // arguments.caller не указывает на setTimeout
}
someFunc.someVar = 'bar';

Волгоградец
10.06.2008, 10:19
Я в замешательстве... Почему вот так вообще не выполняется код:
var i:Number = setTimeout(this, someFunc, 100);
В данном случае this ссылается на объект, который активировал код. Согласно цепочке областей видимости компилятор ищет этот объект вне функции - получается, в setTimeout(). Там не находит и поднимается выше - а это уже _root. Почему же тогда ничего не выполняется?

etc
10.06.2008, 10:32
Надо передавать название метода в объекте, а не ссылку на этот метод.

Волгоградец
10.06.2008, 10:46
А как же хэлп? Во всех примерах стоит this - это же не имя, а ссылка, указывающая на то, что метод выполняется из области видимости вызывающего скрипта.

iNils
10.06.2008, 13:15
__etc говорил об втором аргументе, это не ссылка на функцию, а строка.

Волгоградец
10.06.2008, 13:41
Точно! Невнимательность, блин. Спасибо всем.

Волгоградец
10.06.2008, 20:31
Разрешите еще вопрос. Почему вот это не работает?
var mc1:MovieClip = this.attachMovie ("mc1", "mc1", 1, {_x: 20, _y: 200});
var mc2:MovieClip = this.attachMovie ("mc2", "mc2", 2, {_x: 200, _y: 200});
var i:Number = setTimeout(mc2, "moving", 100);
function moving ():Void{
this._x += 100;
trace (this);
}
Я вроде вызываю функцию из области видимости mc2, следовательно this должен сослться на mc2, но ничего не выводится, даже трейс не дает ничего.

wvxvw
10.06.2008, 20:46
Ну, как бы у mc2 нет такого метода... вот ничего и не вызывается, это ж не Delegate %)
import mx.utils.Delegate;
//
var mc1:MovieClip = this.attachMovie ("mc1", "mc1", 1, {_x: 20, _y: 200});
var mc2:MovieClip = this.attachMovie ("mc1", "mc2", 2, {_x: 200, _y: 200});

function moving ():Void{
this._x += 100;
trace (this);
}

var movingDelegate:Function = Delegate.create(mc2, moving);
// or:
// var movingDelegate:Function = new Delegate(moving).createDelegate(mc2);
var i:Number = setTimeout(movingDelegate, 100);

Волгоградец
10.06.2008, 22:55
Спасибо, Олег. Вроде разобрался.