Scope in AS2 Classes revisited, again.

A while back I did a post or two on handling scope issues in AS2 classes. (This is still something that constantly comes up on Flashcoders, etc.)

To recap, say you have a class, and you create an XML object and load in some XML. you set the onLoad handler of the XML object so that you know when it’s done loading (or not).

class MyClass {
     function getXML(){
          var myXML:XML = new XML();
          myXML.onLoad = function(){
               trace(this);
          }
          myXML.load("some.xml");
     }
}

OK, good enough. But once you’ve loaded and parsed the xml, you probably want to use it somehow in your class. But, from within the xml onLoad handler, there is no reference back to the class! _parent doesn’t work, as that’s a MovieClip property. You could try giving the xml object a property like “owner”, and referencing it in the onLoad handler as this.owner, but the XML object is not dynamic, so you can’t just add properties to it like that.

I wound up going in and creating a new class that extended XML, and added some facilities for it to contact its enclosing class. Others did the same. At the time, this felt like a nice, solid OOP-based solution.

In the many months following that, though, I found that although I ran into this situation almost daily, I rarely, if ever, used that solution. Generally what I wind up doing is creating a local variable just before creating the XML object, and assinging “this” to it. The onLoad handler has access to local variables in the scope where it’s defined. I then use that local var to access the class.

Of course, this method was known at the time, and even mentioned by myself as a possible solution, but I really didn’t like the idea of defining an event handling function within a method of a class. I don’t think nested functions are a really good practice.

In regular practice though, I have comprimised a bit on that viewpoint. I allow myself one line, which calls a class method on the local var reference to the class, passing in the xml data. Looks like this:

class MyClass {
     function getXML(){
          var app = this;
          var myXML:XML = new XML();
          myXML.onLoad = function(){
               app.parseXML(this.firstChild);
          }
          myXML.load("some.xml");
     }
     private function parseXML(someXML:XMLNode){
          // do stuff with someXML
          // the scope is now back to the class itself,
          // and I have all my xml data right here.
     }
}

I’ve found this to be the most pragmatic approach. Same thing applies for onPresses, onStatuses, onChangeds, etc. Of course, if you are using an object that supports _parent, you can skip the whole local variable thing.

This entry was posted in Flash. Bookmark the permalink.

14 Responses to Scope in AS2 Classes revisited, again.

  1. Hi. That’s a very useful approach, Keith. I was using the “owner” method, but as you say this seems more pragmatic as you can point to other objects, vars for transparently.

    tahnks for share it! 🙂

  2. Simon Wacker says:

    Hi. Nice approach. The only thing I would add is the type of the local variable app: ‘var app:MyClass = this;’. You will now get a compiler error when the method parseXML() does not exist.
    What is interesting ist that the compiler does not complain about the parseXML() method being private.

  3. Keith Peters says:

    You’re right, the variable should be typed as well.
    At first I also theought it was odd that the XML object could call a private method of its enclosing class, but it is also a member of the class, so I guess the compiler sees it as ok. Or perhaps because the code is all still within the class definition, the compiler doesn’t see a problem. One of those things I didn’t check in to too deeply because I was just happy it worked!

  4. Peter Elst says:

    True Keith, that makes much more sense than other methods I’ve tried!

  5. Bryan Ledford says:

    I think it doesn’t throw a compiler error because the code lies within the class definition and fools the compiler.

    I am definitely against nested functions. It is just not good OOP. Flash also has some memory leak issues with defining functions within functions.

    Grant Skinner’s XML2 Class is another elegant way of handling the scope issues. It has some nice features such as a timeout, and uses the EventDispatcher interface so you can just listen for a load event. You can even have multiple listeners. http://www.gskinner.com/blog/archives/000070.html

  6. Keith Peters says:

    Actually, if you check Grant’s post, he mentions that his class as partly inspired by my original post. I totally agree that’s the “right” way to do it, and as I said, I generally frown upon nested functions. But in the long run, I found that using a whole other class along with EventDispatcher was just overkill when all I want is for the class to get the load event. By all means, if using an XML2 type class works for you, use it. I”m just sharing my experience and decision.

  7. Joe Martinez says:

    Very useful discussion of the prob. I too will be switching to this method. Thanks!

  8. Flashaddict says:

    As most AS2 developer do, I am using the owner method. That is untill some week ago. Someone said to me the method wasn’t working within his class, so I asked to give me some more information. After taking a look at his class, I found out the way Simon mentioned isn’t working in a class which doesn’t extends a MovieClip. So instead of using var app:MyClass = this;, I uses var app:Object = this. This worked for a class extending a MovieClip, and a class without any inheritance.

  9. Simon Wacker says:

    Quote: “[..] isn’t working in a class which doesn’t extends a MovieClip.”
    Well, I tried it out with the example above and it WORKED and the above class does not extend the MovieClip class.
    The type you give to a variable does not change any behaviour. It just ensures that you get compiler errors or warnings when you do something wrong, like calling a method that does not exist.

  10. Flashaddict says:

    You’re right. I tested it and it worked fine. I still think it is weird it doesn’t worked in the class he gave to me. I will ask him again to send me the class and post it here.

  11. Online Casino Gambling
    Online Casino Reviews
    Riverbelle
    Home Casino
    Aces High
    Lucky Nugget
    Gaming Club Casino
    Jackpot City
    Showdown Casino
    7 Sultans Casino
    Casino on Net
    Phoenician Casino
    Starluck Casino
    Vegas Palms
    Vegas Villa
    adult friend finder

  12. psilo says:

    First of all, the approach is working, which is great. Second, the use of a nested function within another functions scope is BAD. It is NOT considered a memory leak, since it is a one-to-one relation, and is not continiously increasing use of memory. But it is a memory waste, because the activation object becomes persistent. Everytime a function is called, an activation object is created for the current run and added to the function’s scope chain, forming the current scope chain. On end the garbage collector deletes it. In case of a nested function, though, the current scope chain is attached to that function as its own scope chain. The activation object of the parent function is part of the current scope chain, and a reference is now stored in the scope chain of the nested function. The activation object has become persistent and cannot be removed by the garbage collector, along with any local variables it carries. This is the WASTE of memory, especially when variables are string type. Call the function 100 times and you have 100 persitent activation objects along with 100 times the local variables. YAKADEEYAK!!!
    You can, however, release them from memory, when you destroy the class instance, or any other instance holding the code. Normally this would affect your computers perfomance, but in case of Large applications, you should find away to work around this. the XML.onLoad method is, however, a cracker, since we cant even define the function outside, and just assign a refference to it. So… this is probably the best choice, as long as you remember to destroy your instance holding the code after use 😉

  13. Keith Peters says:

    You are right, and I have since studied up on this issue. In any practical sense though, I can’t see it becoming an issue. The initialization object holds the function arguments and any local variables. Let’s go crazy and say that it comes to 100 bytes – a lot of variables with long names. Lets say you wind up with 500 of these in memory. You are now holding on to 50k. That’s not going to affect anything anywhere. I agree it’s bad form, but I can’t see it causing a problem any time soon. I’d be happy to be corrected if someone can give me an example.

  14. Keith Peters says:

    Actually in looking at it further, you wouldn’t keep building up your acitvation objects with each call. You call the function 100 times, it gets overwritten 99 times. Leaving only the latest one in memory. Furthermore, you can throw in a delete onLoad as the last line of the function if you want. This deletes the function and anything attached to it.

Comments are closed.