Elonoa
Elonoa

Reputation: 467

weird behavior of variables in anonymous functions?

Could anyone explain why the trace result of the code below are "5,5,5,5,5" rather than "1,2,3,4,5" and how do you make the anonymous function refer the collect element in the array?( in this example, "var item" should be referring list[0],[1],[2],[3],[4]).

var list:Array=[1,2,3,4,5];
var funcs:Array=[];

for each(var item:int in list){
    funcs.push( function(){
       trace(item);
    });
}

for each(var func:Function in funcs){
    func();
}

trace result: 5,5,5,5,5

Upvotes: 3

Views: 446

Answers (2)

robkuz
robkuz

Reputation: 9934

The problem with your code is that you create a closure which you access later. For what you want to do you need to create multiple closures that can be later accessed.

var list:Array=[1,2,3,4,5];
var funcs:Array=[];

var closure_factory = function(index) {
    return function() { trace(index); };
};

for each(var item:int in list){
   funcs.push(closure_factory(item));
}

for each(var func:Function in funcs){
    func();
}

Upvotes: 3

Rahul Banerjee
Rahul Banerjee

Reputation: 2363

This is the result of two things:

  1. Function-level scope in AS3: the variable declaration inside for each(var item:int in list) is equivalent to declaring a var item:int at the beginning of your function (in your example, at the start of your code).

  2. Anonymous functions are closures, which contain not only the code that you specify trace(item), but also the environment for that code to run in. Specifically, each of the anonymous functions created by your code knows that it should use the item variable (declared at function scope) for printing (via trace()).

So, what happens is that item gets assigned all the elements of list, and then retains the last value (which is 5). It exists (does not go out of scope), and when those anonymous functions fire, each of them looks at the same item and prints the same value.

Upvotes: 2

Related Questions