To _root, or not to _root?

Stacey Mulcahy posted on her blog last night asking “Why is _root evil personified“. I posted a bit of a long-winded reply, which I decided to flesh out and re-post here, mainly so that I have my own record of it to point people to when they ask this question (it seems to come up a lot). She also followed up asking the same question about _global, which can be answered in exactly the same manner.

First off, using _root isn’t necessarily wrong, but it can cause you some major headaches as you move from the world of scripting small Flash pieces to programming larger projects. If you’re building one-offs, prototypes, or other projects that have a limited lifespan, won’t expand, and will never be incorporated in a larger system then there’s nothing wrong with using _root to hack things together quickly. On the other hand, there’s something to be said for learning to do things correctly from the beginning, rather than starting quick-n-dirty then trying to adapt to best practices.

The most important thing is to understand the following implications of using _root, so that you are better able to judge when it is appropriate to do so.


  1. Rigid SWF structure Using _root fixes a structure on your swf that may not exist in all deployment scenarios (you may deploy the swf to be loaded into a larger site framework for example, which shifts _root and breaks your logic. Likewise, you might take the code you wrote and try to apply it to a subclip in a more complex project – suddenly you lose that absolute reference, and your code breaks. This obviously makes your code FAR less portable/reusable. This can be somewhat mitigated by the use of _lockroot, but this is really just a band-aid (and has some limitations I might address in another post).

  2. Poor architecture The use of _root is often a symptom of poor architectural planning. Objects lower in an application object hierarchy (that is, more functionally specific objects) should not directly access objects that are higher in the hierarchy (more project specific). In most cases, communication in this direction should occur via events. Calling _root is the ultimate example of this undesirable tight coupling. The major reason we want to avoid this is to increase code reusability, and reduce the dependency of objects on specific architectures or code structures. I would go out on a limb and say that you can usually make a pretty good judgement about a Flash coder’s architectural know-how by counting the number of references to _root and _global you can find in his/her code.

  3. Naming conflicts _root (and _global) is a shared scope and cluttering it with anything that isn’t qualified by a package opens the door to name conflicts if your code executes in the same player instance as someone else’s who uses this scope. Also, because packages/classes are stored in the _global space, you also run the risk of overwriting entire packages if you are inserting members into _global directly.

  4. Code on the timeline Finally, code on the _root indicates code on the timeline (as we can’t currently bind a class to the _root), which is generally something you want to avoid in larger projects.

So how do you work around using _root and _global? Most people use these two objects as a place to create absolute paths to objects, data or functions that are used throughout the project. This capability can be replicated by using the Singleton pattern instead, which solves most of the problems listed above by contextualizing your code (with the possible exception of #2, but that is the subject of a whole other debate). Similar results can be achieved using classes with static members.

// SingletonExample by Grant Skinner, http://gskinner.com/
class com.gskinner.foo.SingletonExample {
// public vars:
public var bar:Number = 20;
// private vars:
static private var instance:SingletonExample;
// initialization:
// constructor is private to
// discourage direct instantiation:
private function SingletonExample() {}
// public methods:
// method to get the single instance of this class:
public static function getInstance():SingletonExample {
if (instance == undefined) {
instance = new SingletonExample();
}
return instance;
}
}
// in another class:
import com.gskinner.foo.SingletonExample;
...
myBar = SingletonExample.getInstance().bar;

There are obviously a number of places where you do have to use _root, but these are all special cases dictated by the Flash environment. Examples include the use of FlashVars and global coordinates (ex. for shape flagged hitTests or globalToLocal).

So in summation: _root is not inherently evil, it has it’s uses but it also has some serious implications that you should fully understand before you use it willy-nilly.

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

27 Comments

  1. In other words: _root doesn’t kill Flash. People who use _root kill Flash.

    um…

    If _root is outlawed, only outlaws will use _root?

    bye!

  2. To not use _root is a choice that you, the developer has to make. People who have made big apps in flash learn to hate _root because of the debugging / hair pulling they had to do because of using it. So debugging big app + used _root in app == devil incarnate.

  3. Goddamn you are long winded! And, i thank you for that 🙂

  4. If you use loadMovie and then run code from the loaded movie, variables like _root.foobar are undefined in in the loaded Movie. I just spent two days (and tearing out lots of hair) discovering that fact. So NO more _root, I’m using _global everywhere from now on!!

  5. Why no _root and _global?

    There are two discussion goin on at Stacey Mulcahy’s Blog, to or not to *”_root (to use or not to use _root)”:http://www.bitchwhocodes.com/mt/archives/000218.html * and *”_global (to use or not to use _global)”:http://www….

  6. Scott Hyndman March 1, 2005 at 12:58pm

    You can bind a class to _root using __proto__.

  7. _global isn’t exactly the replacement for _root either. _global has problems in that the variable is not tied to anything in particular. It is just available to any class, any timeline, anywhere. Sometimes this is good for convenience. Variables can be local, class wide, and global in scope (I know I am oversimplifying this right now). Given those scopes you should find the right use for the right variable. In most cases I have found for larger scale projects, creating custom classes and then using that class to store variables class wide is useful. It helps organize my project’s flow. And unlike global keeps me from using it anywhere, somewhere else I may not want to use that variable.

  8. Thanks Grant. That’s a useful explaination about why _root can be bad.

    One question though, and perhaps I’m showing my ignorance here, but can _global and _root really be viewed to be the same in terms of inappropriate usage? Todd Coulson makes a good point about _global and it’s usefullness and pitfalls, but are we not constantly referencing _global when we refer to a class? I can see why staying away from polluting _global with one-off variables is a good idea, but isn’t not using _global in references bad practice? When we refer to:

    myBar = SingletonExample.getInstance().bar;

    Isn’t SingletonExample really sitting on _global (if I understand where classes are born in AS2)?

    What if I happened to have a movieclip called SingletonExample (ok, it’s a stretch, but bear with me) in the same scope as where I’m declaring myBar. Should I not reference _global.SingletonExample to ensure I have the class?

    My example is a little extreme perhaps, but I don’t see _global in the same way I see _root. _root means different things depending on where you are calling it from, but _global is _global from anywhere, no?

    Maybe I just need to take one of your classes and I’ll see the light.

  9. On the project I am working on at the moment SWF’s can be pulled into other frameworks and used anywhere in the site, nested within other swf’s, once built it must be totally portable.

    All our code has to be in external classes and quickly reused with little or no re-engineering.

    _root and _global would bretch portabilty requirements. Not really suitable for the type large project work we are doing.

    Once you get used to it as a workflow you never want to go back to older methods

  10. Derek’s comment about classes belonging to _global is absolutely right. The nice thing about _global, though, is that once something is defined on the object is no longer needs the reference. _global.MyClass can now be called as just MyClass. The Singleton pattern is very cool and has many uses, but to just store data with no methods you don’t need to go out of your way to write and import an extra AS2.0 file. It is just as easy to keep your data defined to an object created at runtime specific to your app. So _global.mazeData = new Object(); can now hold many global variables for your game, such as mazeData.playerName = “Grant”; It’s nothing new or cool, but it does the exact same thing. _global does have it’s problems though, whether you define directly to _global or in an AS2.0 class (also on _global). I’m still trying to figure out the exact situation, but in certain circumstances _global is not universal accross loaded SWF’s. I’m not sure if it is when they’re loaded into seperate _levels or when they’re from different domains… There are always issues with large projects, just do the best you can with what you’ve got… just make sure it’s an INFORMED decision.

  11. “The nice thing about _global, though, is that once something is defined on the object is no longer needs the reference”

    Dangerous ground!

    If there’s one thing I’ve learned about working in Flash is that scoping shouldn’t be left to the player to figure out. Yes it works, but bad things can happen when you don’t specify. The first guy I read preaching about this in FlashCoders was Tony Macdonell (no doubt there probably were others before him).

    Now everyone try this:

    1. Drop an MX04 Button component on the Stage.

    2. Draw a rectangle and make it a movieclip – or create an empty movieclip, doesn’t really matter.

    3. Call the movieclip whatever you want in the Properties dialog, but give it the instance name of “mx” (without quotes).

    4. Test movie.

    Bye, bye components.

    If you create a variable, movieclip, whatever, called mx on _level0, none of the component styles will work.

    Forget _root, that is what I call bad coding practice.

  12. Camille Reynders May 3, 2005 at 2:23am

    Wouldn’t it be easier to do a singleton implementation as follows:

    class someClass{

    static private var __this:someClass=new someClass();

    private function someClass(){

    }

    }

    That way you don’t need a separate method getInstance anymore, because the instance is automatically created when the class is referenced to.

    Or is this bad habit???

  13. @Camille – The reason getInstance is used is because of lazy instantiation – the singleton is only created when it is requested. Imagine an application with 50 singletons… using the static initialization method there will be a big performance hit initially to create all of the instances, since static initializers run right away. By using lazy instation and delaying the instantiation until absolutely necessary we can spread that performance hit over the lifetime of the application, and speed up the initial loading time.

  14. just building a grid with a simple for loop… obviously x and y change but this is code that matters …

    this.x0.duplicateMovieClip(“x”+i, i, 0);

    this[“x”+i]._x = xAmount;

    this[“x”+i]._y = yAmount;

    that does not work …

    but this does …

    _root.x.duplicateMovieClip(“x”+i, i, 0);

    _root[“x”+i]._x = xAmount;

    _root[“x”+i]._y = yAmount;

    How is this problem solved without using root .. I don’t think it can be based on the syntax of flash?

  15. Greg:

    I disagree. The code you provided works fine, as it is in fact IDENTICAL to the code using _root, providing that x0 is in the movieclip calling this code. If x0 is sitting on the root, then the code will only work if it’s on the root.

    Below is a simplified version:

    var clip = x0.duplicateMovieClip(“x”+i, i);

    clip._x = xAmount;

    clip._y = yAmount;

  16. “If there’s one thing I’ve learned about working in Flash is that scoping shouldn’t be left to the player to figure out. Yes it works, but bad things can happen when you don’t specify.”

    Flash behaves in a very predictable manner if you know what its scope resolution is. There is no way of completely avoid naming conflicts in ActionScript (prior to AS3) except through mindful coding.

    “give it the instance name of “mx””

    If you are coding with Macromedia components it makes sense to me that you would treat “mx” as a reserved word. Likewise, with any framework or package they should exist under a single unique name (“mx” is pretty unique – it wasn’t named “btn” or “components”). This is exactly what creating an object literal or a singleton on _global is for.

    The best thing is to be aware of the system you’re developing in enough to know these major _global packages. A bit of code right up front can help with that:

    ASSetPropFlags(_global, null, 0, 1);

    for (var i in _global) {

    trace(“avoid: ” + i);

    }

  17. DUDE. I’ve been saying this for ever. Very well discribed. Thanks.

  18. Maneesh Bidaye March 4, 2007 at 8:22pm

    Straight up, I’m really new to Actionscript, but I surprise myself to have the concept summarized well.

    _root is no good at all 4 many reasons, mainly that nested SWFs lose scope of their own “root” and mess up the state of _root on the main timeline.

    _global’s pretty good, but eventually, you’ll have a tonne of code on the timeline representing all the data (even if you organize the data in obj’s on _global)

    Singleton is great! Yes, it’s a file with just data in it, but it’s reusable and it stays off the timeline.

  19. thanks for useful tips guys

  20. I don’t get it. I don’t understand your “work around using _root and _global”.

    If I have a movie inside a movie, why not just use this._parent instead of _root to prevent going all the way down to the root of the main movie. Isn’t “this.” only talking about “this” movie and nothing below? Or am I wrong? Is using “this.” also just as bad somehow?

  21. The _Root of all evil, indeed! 🙂

  22. thanks for that! resolves my problem!

  23. I hope someone can help me I don’t use root often but I am using cuepoints to cue up fades and only root seems to work. What can I do?

    code

    import mx.transitions.*;

    var listenerObject:Object = new Object();

    slide1._alpha = 0;

    slide2._alpha = 0;

    slide3._alpha = 0;

    slide4._alpha = 0;

    listenerObject.cuePoint = function(evtObj){

    trace(evtObj.info.name);

    trace(evtObj.info.time);

    var fadeTween:Tween = new Tween(_root[evtObj.info.name], “_alpha”, none, 0, 100,2,true);

    }

    vidNarrator.addEventListener(“cuePoint”,listenerObject);

  24. Where would I find good tutorials for learning how to develop without relying on _root?

  25. Sad thing is I’m using one of the in-built flash quiz applications and it has root all over it.

    I’m struggling to get it to work in an embedded program

  26. Seems to me that using a Singleton — widely viewed as an anti-pattern in the Java and other language communities — resolves nothing here, except to make your code cleaner. To REALLY avoid this problem, your Singleton would have to be provided by a factory that knows, based on the context (or a String as a parameter, or something) which one of them is desired.

    Obviously the timeline sucks and Singleton sucks a bit less, but in terms of the design/architectural problem of using root, Singleton is equivalent… you hint at this in by saying it doesn’t solve #2.

  27. I am struggling with a situation where I appear to have two different _global.activityactive variables. Setting the value in one part of my project doesn’t change how it traces in another. I am completely vexed and may just change all the references to static properties of an Environment singleton.

    I have no idea how calling a method can break _global references.

Leave a Reply

Your email address will not be published. Required fields are marked *