// you’re reading...

ActionScript 3

Listen to me rant about ActionScript, part 3

So after a three week vacation, I think I’m finally ready to dive into a few other fun pieces of ActionScript.  And really, what better place to start than local variable hoisting.

In Java and C++, local variables are scoped per block, starting at the beginning of a function.  Each set of curly braces corresponds to a scope, and scopes move from top to bottom.  Each scope contains the definitions defined within, and a link to the scope above it.  If a variable is defined in a parent scope, let’s say in a for loop that contains an if statement, the variables from the for loop will be accessible to those in the if statement.  But, the variables from the if statement aren’t visible to the for loop.  Pretty standard, top-down scoping that almost every intro to programming book or course covers from the beginning.  And this well-established precedent is exactly how ActionScript works, right?  Sadly, no…

ActionScript uses a technique called hoisting.  Any variable defined within a function scope, in any structure, at any location, is automatically moved at compile-time to the top of the scope.  And it’s accessible anywhere in any of those scopes.  In most languages, this would be a compile error.  But not in ActionScript, which is really like the wild west sometimes.  

So let’s take a look at this to really let it sink in:

function myASFunction():void {
     myFlag = true;
    if(myFlag) { //defined way below from a different scope
          myMessage += ” What am I?”;
          trace(myMessage); //will print What am I?
     }
     var myFlag:Boolean = false;
     var myMessage:String = “WTF?”;
}      

 

void myJavaFunction() {
     boolean myFlag = false;
     String myMessage = “logical”;
     if(myFlag) {
          System.out.println(myMessage); //everything in the right place
     }
}

Weird, right?  But it gets better actually.  And by better I mean worse.  While variables are hoisted, assignment expressions are not.  So in my code example, myMessage doesn’t gain it’s initial assignment until the assignment is reached in code, even though the declaration has been hoisted and modified.

With the amount of confusion and weirdness that this feature introduces, you have to ask “why?”.  And if anyone has a good answer, I’d love to hear it but I’ve never heard a compelling enough argument to convince me that variable hoisting is a good idea.  Or even an ok idea.

So, what does Flex Builder do here?  Nothing.  Nothing at all.  When we were initially writing the language intelligence engine, we decided that not only was variable hoisting a terrible idea, but that no one would use it.  And if they did use it, they weren’t doing it on purpose.  So we simply decided not to support it.  And to this day, we haven’t heard a single request for hoisting support.

Later this week, I’ll post about another thing we punted on: functions as constructors for core data types.

Discussion

11 comments for “Listen to me rant about ActionScript, part 3”

  1. HI, Im not sure what you mean.

    Your actionscript function will not trace anything as (myFlag) is not true at that point in the method.

    Try compiling it in flash and see for yourself.

    cheers,

    MaTT

    Posted by matt | January 26, 2009, 12:45 pm
  2. compile this as see for yourself, its never true

    function myASFunction():void {
    trace(‘myFlag = ‘ + myFlag); // is false
    if(myFlag) { //defined way below from a different scope
    myMessage += “What am I?”;
    trace(myMessage); //will print What am I? // no it wont
    }
    var myFlag:Boolean;
    trace(‘myFlag = ‘ + myFlag); // is false
    var myMessage:String = “WTF?”;
    trace(‘myMessage = ‘ + myMessage); // will print ‘myMessage’;
    }
    myASFunction();

    Posted by matt | January 26, 2009, 12:50 pm
  3. I have been burned by this many times and the fact that FlexBuilder does nothing about it is disappointing to say the least. While this situation does not normally arise by design it can arise quite frequently by accident when editing large code blocks (e.g. cut and paste code from bottom of a block to top of the block above the variable decl.).

    IMHO, FlexBuilder should at minimum issue a warning when this occurs as it is most likely a coding mistake, and have the option of forcing an error during compilation to require correction.

    Posted by George | January 26, 2009, 12:59 pm
  4. Hey Matt-

    I just updated the code to initialize myFlag to false before it’s declared. And it will compile just fine, and in my tests it will print “null What am I?”

    Thanks for the catch!
    -David

    Posted by David Zuckerman | January 26, 2009, 1:02 pm
  5. Hi George-

    Flex Builder should issue a warning, but it’s part of the language so it’s a fine line. The Flex compiler currently doesn’t track this as an error (even though I think it should), and the compiler is what we use to issue warnings to the user.

    You should file a bug with us to get it on our radar.
    http://bugs.adobe.com/flex
    -David

    Posted by David Zuckerman | January 26, 2009, 1:04 pm
  6. Hey there. Stumbled on your blog while randomly surfing the web.

    I believe AS3 hoists variables to be compatible with ECMAScript, and ECMAScript hoists variables to be compatible with JavaScript 1.5. When I was at Adobe, getting 100% ECMA compliance was a major goal. Not sure if things have changed since I left.

    As for the language construct, I am not sure exactly how variable hoisting got introduced in JS1.5, but my guess is that ease of implementation was the big reason there. The ES4 discussion lists seem to indicate that most people there don’t like the hoisting behavior.

    For my money, the Flex compiler should probably retain the behavior in the compiler, but warn about referencing hoisted variables before they are declared. As for FB behavior, I agree with your assessment that no one does this on purpose so there’s no need to support it.

    Hope all is well w/you.

    Posted by Sho | January 26, 2009, 1:04 pm
  7. Hey Sho, nice to hear from you!

    And you’re right, hoisting was introduced by the ECMAScript group for compatibility. And before the ES4 split, it was a huge priority for Adobe and AS3 to stay as language compliant as possible. Not sure if you’ve followed the Harmony proposal from the ECMAScript group, but it’s a far cry from ES4 and the current incarnation of ActionScript. Really, they look almost nothing alike and the chances of us being compatible look slim right now.

    I can’t speak on the future of AS3 because really, I don’t know where it’s going and I’m not sure Adobe does either. But at this point, I’d like to see us break from ECMAScript. All languages have their problems, but AS3 seems to have complexity issues inherited from ECMAScript that don’t help the people using the language. To name a few, the lack of abstract classes and private constructors has led to countless complaints. And the addition structures like namespaces have just led to confusion.

    Regardless of what happens, the future will be interesting.

    Posted by David Zuckerman | January 26, 2009, 1:14 pm
  8. Just decided to comment that I like your posts on the meter. As programmer with knowledge of .Net and Java I often find AS3 little bit troubling…

    So keep them coming may be then more people will pay attention to those and Adobe eventually will pay attention too.

    There are few other problems that bug me from time to time… Biggest I think is Event model flaws. No event model is way better then AS2 and way closer to proper event models but EventDispatcher seriously lacks methods like getEventListenersNum, getEventListenerAt, removeEventListenerAt, ClearEventListeners… I think I can write my own EventDispatcher class that will include those but that will not solve problems I am having sometimes for all classes that inherit original EventDispatcher :(

    And those include such cases like having memory leaks because of strong linked event listeners and that some objects don’t have links to them in your program anymore but stay somewhere there and still catching events and eating processor time and memory…

    Or other problem is that EventDispatcher does not check for duplicates or something and I need to make my own flags in objects and track their state to see if some kind of events listeners already registered or not…

    And yet another big lack is operator overloading :( I stumble on need for it pretty often and may be it is not “must” thing but in combo with no proper code hints in some editors it becomes a true hell :( Also making static class member functions to simulate constructor overloading is messy sometiems too :(

    Posted by wonderwhy-er | January 27, 2009, 3:27 am
  9. It’s from Lisp, via scheme, self, javascript, and ECMAScript. Unfortunately we lost “let” along the way.

    Posted by Josh McDonald | January 28, 2009, 4:04 am
  10. [...] pm A while back I read a post about variable hoisting in Actionscript , and remember thinking how it was weird how that was the first time I’d ever heard about that, and [...]

    Posted by FlashApe » Blog Archive » Burned by hoisting | March 18, 2009, 11:08 pm
  11. hoisted by your own petard? :)

    Posted by AJ | March 21, 2009, 6:24 am

Post a comment