Declaring variable in loop or before loop in AS3? - actionscript-3

Should I declare the _mcContainer var before the loop or no? (performance increase?)
for(var i:uint = _startIndex; i <= _endIndex; ++i){
var _mcContainer:MovieClip = _mcParent["i_" + _position];
}
or
var _mcContainer:MovieClip;
for(var i:uint = _startIndex; i <= _endIndex; ++i){
_mcContainer = _mcParent["i_" + _position];
}
?

It's not hard to test...
...however according to the docs, it shouldn't make any difference because variable declarations are hoisted to the top of the method block anyway.
From the docs:
An interesting implication of the lack of block-level scope is that you can read or write to a variable before it is declared, as long as it is declared before the function ends. This is because of a technique called hoisting , which means that the compiler moves all variable declarations to the top of the function.

Related

How can this be the output?

It is simple program, but the output of the program is so unexpected .
Programming language : ActionScript 3.0
So, we have 3 kinds of syntax:
// 1. Variable declaration.
var a:int;
// 2. Assign value to variable.
a = 0;
// 3. Declare variable and assign value in one go.
var b:int = 1;
The tricky moment is that in AS3 variable declaration is NOT an operation. It is a construction that tells compiler you are going to use a variable with a certain name and type within a given context (as a class member or as a timeline variable or as a local variable inside a method). It literally does not matter where in the code you declare your variables. AS3 is, I must admit, ugly from this very perspective. The following code might look weird yet it is syntactically correct. Lets read and understand what it does and why.
// As long as they are declared anywhere,
// you can access these wherever you want.
i = 0;
a = 0;
b = -1;
// The 'for' loop allows a single variable declaration
// within its parentheses. It is not mandatory that
// declared variable is an actual loop iterator.
for (var a:int; i <= 10; i++)
{
// Will trace lines of 0 0 -1 then 1 1 0 then 2 2 1 and so on.
trace(a, i, b);
// You can declare a variable inside the loop, why not?
// The only thing that actually matters is that you assign
// the 'a' value to it before you increment the 'a' variable,
// so the 'b' variable will always be one step behind the 'a'.
var b:int = a;
a++;
}
// Variable declaration. You can actually put
// those even after the 'return' statement.
var i:int;
Let me say it again. The place where you declare your variables does not matter, just the fact you do at all. Declaring variable is not an operation. However, assigning a value is. Your code actually goes as following:
function bringMe(e:Event):void
{
// Lets explicitly declare variables so that assigning
// operations will come out into the open.
var i:int;
var score:int;
for (i = 1; i <= 10; i++)
{
// Without the confusing declaration it is
// obvious now what's going on here.
score = 0;
score++;
// Always outputs 1.
trace(score);
// Outputs values from 1 to 10 inclusive, as expected.
trace(i);
}
}

Add iterations to loop AS3

Hi something simple is annoying me and I'd like some help!
function highlight(textField:TextField):void
{
var l:int = textField.text.length
for(var i:int = 0; i < l; i++)
if (!highlightChar(textField, i))
l++;
}
This loops through a character string to add a box behind the character for a highlighter affect. Some of the characters fail (the bounding box is null, assume these are returns etc) and in the example I'm looking at it returns false 5 times, and the boxes are 5 characters short. I'm attempting to add another iteration when it fails to keep going for another 5 characters, but this loop never stops.
Is there another way of doing this?
Hacky solution - collecting the fail count and then doing another loop after the first one finished has fixed it
if(fails > 0)
for(var f:int = i; f < fails + i; f++){
var box:Shape = highlightChar(textField, f);
if(box) boxes.addChild(box)
}

Under what circumstances is a reverse for loop faster in Flash and why?

According to Adobe, a reverse for loop is the fastest way to do a loop:
http://www.adobe.com/devnet/flash/articles/optimizing-flash-performance.html
I could not create a test where a reverse for loop was consistently faster than a normal loop, but I'm assuming Adobe knows Flash. Does anyone know under what circumstance this is true and why?
You don't have to recalculate the length of an array or Vector if you iterate backwards.
for(var i:int = list.length; i > 0; i--)
// -------------^^^^^^^^^^^ Length is calculated once for the start value.
Versus:
for(var i:int = 0; i < list.length; i++)
// --------------------^^^^^^^^^^^ Length is calculated for each iteration.
FYI, the difference is speed is negligible. I personally use whichever is more readable to me (the former).
That aside - if you are iterating over a collection where all objects are of the same type, you should be using a for each loop. This is much faster, more readable and more logical than either of the above. The reason that it is faster is because no type conversion is required at each iteration - the type is set when you define the loop:
var strings:Array = ["a","b","c"];
for each(var i:String in strings)
{
trace(i);
}
Marty is correct: if you use a reverse for loop you have to get the length value only once. However, this can be easily achieved through a normal for loop, and assigning the length to a variable beforehand.
A further optimized reverse for loop would look like:
for(var i:int = list.length; i--;)
which results in looping through every element in the array in reverse without a third for loop argument.

As3 - Get Movieclips That The Name Start With A Specific String

I'm making a tile based game where ta_*(number)* and ca_*(number)* acts like bins. You drag things towards it and drop. But the level may put several these tiles.
I am not going to make something like:
if (my_mc.hitTestObject(ta_0) || my_mc.hitTestObject(ta_1) || my_mc.hitTestObject(ta_2).........)
Because some may not exist and throw an error at me, and I don't want to make like hundreds of them.
Is there a way to find movieclips on stage that start with the name "ta_" and "ca_"?
So that I can get: ta_1, ta_2.....?
No, you can't. Unless you loop on getChildAt() and check all children's names.
But, why don't you add your bins to an array when creating them?
(I assume you create them dynamically)
var myBinArray:Array = new Array(10);
for (var i:int = 0; i < myBinArray.length; i++)
{
var myBin = new Bin();
myBinArray[i] = myBin;
}
Then you simply loop on your array:
for (var i:int = 0; i < myBinArray.length; i++)
{
if (mybinArray[i] != null)
if (my_mc.hitTestObject(mybinArray[i])
{
// statements
// and here I assume you want to break for loop
}
}

For-loop variable scope confusion

I have noticed a weird behavior of the variables in for loops. It's not really a problem, but it disturbs me a lot.
Actually I've created two loops this way:
for (var i:uint; i<19; i++) SomeFunction (i);
for (var i:uint; i<26; i++) SomeOtherFunction (i);
What I received was a compilation warning:
Warning: Duplicate variable definition.
This warning really surprised me. Nothing like that ever happened to me in other languages.
It seems that the i variable gets into the scope that is higher in the hierarchy and becomes available out of the loop's block. I've also tried to embrace the loop block in a curly brace, but it didn't change anything.
Why does it happen? Is it normal? Is it possible to avoid it? For now I've just set different names for both of the variables, but that's not a real solution I think. I'd really like to use the i-named variable in most of my for-loops.
yes, the loop increment variable is in the scope of the loops parent, not inside the loop itself. This is intentional, for examples like this:
public function getPositionOfValue ( value:String ) : int
{
for ( var i:int = 0; i < someArray; i++ )
{
if (someArray[i] == value )
{
break;
}
}
return i;
}
this allows you to access the value of i once the loop is over. There are lots of cases where this is very useful.
What you should do in the cases where you have multiple loops inside the same scope is var the i outside of the loops:
public function getPositionOfValue ( value:String ) : int
{
var i:int;
for ( i = 0; i < 15; i++ )
{
//do something
}
for ( i = 0; i < 29; i++ )
{
//do something else
}
return i;
}
then you get rid of your warning. The other thing to consider is to name your loop increment variables something more descriptive.
Update: Two other things to consider:
1) you shouldn't use uints except for things like colors and places where Flex expects a uint. They are slower than int's to use. Source]1 Update: it looks like this may no longer be the case in newer versions of the flash player: source
2) when you var a loop increment variable inside of a loop declaration, you want to make sure you set it to the proper initialization value, usually 0. You can get some hard to track down bugs if you dont.
As mentioned here, as3 has global and local scope and that's about it.
It does not do block-level scoping (or for-level either). With hoisting, you can even write to variables before you define them. That's the bit that would do my head in :-)
Early versions of Visual C had this bug, leading to all sorts of wonderful funky macro workarounds but this is not a bug in as3, it's working as designed. You can either restrict your code to having the declaration in the first for only or move the declaration outside all the for statements.
Either way, it's a matter of accepting that the language works one way, even though you may think that's a bad way :-)
Declare the variable i outside the loops to avoid this. As long as you reset it (i=0) you can still use it in all loops.
var i : uint;
for (i=0; i<19; i++) SomeFunction(i);
for (i=0; i<26; i++) SomeOtherFunction(i);