Leo's Technical Blog

A Closure-Related Gotcha on Flex 2 (AS3)

Introduction

user

Leo Soto


tips, debugging, actionscript

A Closure-Related Gotcha on Flex 2 (AS3)

Posted by Leo Soto on .
Featured

tips, debugging, actionscript

A Closure-Related Gotcha on Flex 2 (AS3)

Posted by Leo Soto on .

This is one of these write-it-so-you-will-never-forget blog posts. Because I spent much time spotting the bug on code that used closures to simplify the code. It is not practical to show the actual code here, so I will make a dumb "clone" of the relevant section:

  
function doSomething() {  
    for (var i = 0; i < 10; i++) {
        var foo = makeFoo();
        foo.addEventLister(ResultEvent.RESULT, timeLogger(i));
    }
}

function timeLogger(i) {  
    return function(event) {
        Logger.debug("Received request number ", i);
        for(var i = 0; i < 100; i++) {
            // For some reason this loop had to exist.
        }
    }
}

[If you are curious, I did not included the inner anonymous function inside doSomething, because all instances of the function would "close over" the same reference to i]

As you can see, the idea was to add some timers for some asynchronous events. See the bug? Yes? I envy you! No? Well, unless you have psychic debugging abilities, it is hard to say without knowing the observed, wrong behaviour: Every logged request had an "undefined" number. That i was always undefined. WTF!?

The bug is the formal parameter i of timeLogger conflicting with the loop variable i on the anonymous inner function. You change either variable name, and the problem is solved. Ta-da!

I suppose this is a side effect of the static analysis and typing made by the ActionScript compiler. This gotcha does not currently apply to JavaScript, because of good old interpreters "dumbness" prevent them to bind variables to definitions that are ahead on the code. But I question the fact that such "clever" idea is a good one. In fact, I do not see a single use case for it.