By Dan Carr
 
Modified
18 January 2011
 

Requirements

 
Prerequisite knowledge

You should have some familiarity with ActionScript 2 and Flash Professional.
 

 
User level

Intermediate
 
This article provides an overview of key concepts that will help you migrate your applications to Adobe ActionScript 3. When I first started building ActionScript 3 apps, the hardest thing for me to get used to was the changes to the simple commands that I had used for years. Where did the attachMovie method go? Where did everything in the MovieClip class move to? It felt like I had to learn to walk again right before a big race.
 
In the years following the Adobe Flash CS3 release, I have worked full-time producing ActionScript 3 SWF and Adobe AIR applications. I laughed, I cried, I hit the wall (figuratively) a few times. In the end, I have to say that it's hard to picture going back to ActionScript 2. On a general level, the great thing about ActionScript 3 is that everything is standardized: there's one way to create instances, one way to work with events, and so on. If you're new to coding ActionScript, there may be more to learn but it's easier to learn and ultimately a good place to start.
 

 
Changes to the core language

The following sections describe fundamental changes to the core language syntax in ActionScript 3.
 
 
Code placement
One of the most noticeable changes from prior versions of ActionScript is that you can no longer place code directly on an instance. ActionScript 3 requires that all code be placed on keyframes on a timeline or in ActionScript classes associated with a timeline. That means that you can no longer place code directly on a button or movie clip instance as you might have in the past.
 
While this change may take some getting used to, in the end it promotes better coding standards and creates projects where the code is easier to follow. As a best practice, you should add an "actions" layer to the top of any timeline's layer stack and add your code to keyframes on this layer. If possible, try to add your code to frame 1 to make it easier to find. Of course you can place stop actions wherever you need them. If you've work with code in your FLA file before, using an actions layer probably isn't a new concept but be aware that adding code to the timeline is now required.
 
 
Using data types
ActionScript 3 uses the new ActionScript Virtual Machine 2 (AVM2) in Flash Player 9 and later to render code in an optimized environment. One of the key concepts related to optimization is using the data type syntax whenever you declare variables, functions, or elements in your loops. Doing so allows the Flash compiler to check your code and identify errors at compile-time as well as run faster and more efficiently at runtime.
 
The following statement shows a variable declared as a String data type:
 
var username:String = "Dan Carr";
Notice that the variable name is followed by a colon and the name of the data type. ActionScript 3 is a strictly typed language. By declaring the variable as a String, you're basically saying that the variable container can only hold literal string content and that Flash Player should allocate memory accordingly. If you were to try to fill the variable with a number or an array, the compiler would throw an error or you would receive a runtime error in the SWF.
 
Tip: Flash Professional CS5 has improved the Actions panel support for code hints. When you add a colon in your variable declaration the Actions panel will show you a list of options for the data type.
 
 
Changes to using variables
Variables as essentially the same in ActionScript 3 as they were in prior versions with the following exceptions: you must use the var keyword to declare a variable and you must data-type the variable while declaring it. Omitting the var keyword will produce an error. Omitting the data type will produce a warning or an error depending on the environment in which you're writing the code.
 
 
Changes to using functions
Functions are also essentially the same in ActionScript 3 except that the arguments and return type must be data typed in the function declaration:
 
function gotoURL( url:String ):void { navigateToURL(new URLRequest(url)); }
Notice in the sample above that the incoming argument "url" is data typed as a String and, since there is no return data type, the void keyword appears after the parenthesis. In ActionScript 3 the void keyword is spelled with a lowercase v. It's important to note that ActionScript 3 is case-sensitive.
 
 
Changes to using events
There are two significant changes to how events are written in ActionScript 3: there is only one syntax for writing an event, and event code cannot be placed directly on an object instance. In ActionScript 3 you write your event code in a similar manner to the way you did for ActionScript 2 components. Responding to an event requires that you write an event handler function and that you register with function with the object broadcasting the event using addEventListener.
 
See the Working with events section of this article for more details.
 
 
Other changes to the core language
The good news is that the bulk of the core language of ActionScript is still the same. ActionScript 3 is still based on the ECMA standard. You create arrays, objects, dates, and the range of core language syntax such as loops and conditional statements as you previously had.
 
Check out the Learning ActionScript 3 help pages and the Core ActionScript classes section of the ActionScript 3 Developer's Guide for more details.
 

 
Working with movie clips

The following sections describe fundamental changes to how movie clips are perceived in ActionScript 3.
 
 
Movie clips are now display objects
In prior versions of ActionScript, the MovieClip object was the center of the universe as it contained all the commands for working with timelines and visual content. Though the MovieClip class worked well for controlling animations, it had some disadvantages in structure, flexibility, and granularity of its application programming interface (API).
 
The first thing I noticed in ActionScript 3 was the updated MovieClip API. In ActionScript 3, the MovieClip API no longer contains many of the commands I used routinely. One of the improvements of the ActionScript 3 language is the change in the granularity of the APIs. The majority of the MovieClip API has moved to the DisplayObject and DisplayObjectContainer classes, which the MovieClip class inherits from. The MovieClip API is now used primarily to traverse a timeline.
 
You need to know this information as you'll probably spend some time looking through the ActionScript 3 Help documentation to find what commands are available. Here's the list of the classes from which the MovieClip class inherits:
 
Notice that the MovieClip class subclasses the Sprite class. A Sprite is essentially a movie clip without a timeline. It's lighter weight and recommended for creating visual objects that don't need access to timeline control.
 
To find out everything a movie clip can do, review the documentation for each class in the inheritance chain.
 
 
Nested timelines are now the display list
Creating nested levels of movie clip instances has been a part of Flash since long before ActionScript was a player in the mix. When ActionScript first evolved it treated movie clips in code the same way it treated movie clips at authortime. In ActionScript 3, this isn't the case.
 
Timelines in ActionScript 3 are perceived through the notion of a display list. The display list has a single stage property and a root property for each SWF loaded into the movie. When movie clips and other visual objects are instantiated in ActionScript they are not explicitly assigned to a timeline. It's an odd notion if you have experience dynamically creating movie clips, but it has the advantage of being able to instantiate a movie clip and have it remain invisible until you decide to show it in the display list. Furthermore, you can display the new instance in any timeline you like, not just the timeline it was instantiated on.
 
Movie clip instances are display objects when they are instantiated. When a movie clip instance is associated with the display list, the movie clip then becomes active in the display list. That means two things. First, child instances can be instantiated and configured at any time but they cannot be seen until the parent movie clip is added to the display list. Second, until the movie clip instance is added to the display list, it isn't capable of accessing the stage, parent, or root properties of the display list. This change in timing creates some new considerations in ActionScript 3.
 
In ActionScript 3, you use the addChild method to see a display object appear on the Stage. For example, suppose that you want to create an instance of a ComboBox control from the library. To see the instance appear on the Stage, you would use the following code:
 
import fl.controls.ComboBox; var myCombo:ComboBox = new ComboBox(); // This produces an error trace(myCombo.stage) // This works addChild(myCombo); trace(myCombo.stage)
The addChild call above adds the myCombo instance to the display list. At that time the myCombo instance appears on the Stage and gains access to the stage, root, and parent properties. Notice that instead of using the attachMovie method, the myCombo instance is created using the new keyword. You use the new keyword as a standard way of instantiating all objects in ActionScript 3.
 
 
Instance validation
ActionScript 3 displays an error when you try to access an instance that is undefined. Often this happens when you declare a variable reference for the instance but haven't actually instantiated an object into the reference and added it to the display list. It's a timing issue in most cases.
 
To validate against an undefined instance in the display list, use the getChildByName method, as shown in the following code:
 
var myInstance:MovieClip = getChildByName("instanceNameInQuestion"); if( myInstance!= null ) { // Then do something... }
The code above uses the instance name to test if the instance exists in the display list. If the result is null, then the action isn't performed and an error does not occur. You can also use try..catch statements to prevent player execution from stopping due to an unhandled error.
 
 
Movie clip property changes
In ActionScript 3, the underscore (_) has been eliminated from the property names. In some cases, the way that values are set for common properties has also been updated.
 
The alpha property of a movie clip is now set on a scale of 0 to 1 instead of 0 to 100. For example, 50% opacity would be set as follows:
 
myInstance.alpha = 0.5;
The scaleX and scaleY property of a display object are now set in a similar way. For example, 150% of normal scale would be set as follows:
 
myInstance.scaleX = 1.5; myInstance.scaleY = 1.5;
 
Using this, _root, _parent, and _global
The this alias can be used in ActionScript 3 and it behaves as it does in previous versions of ActionScript. The _global path does not exist in ActionScript 3. Try to create a class with static properties if you need to use global references in ActionScript 3. The _parent property can be accessed as the parent property of any display object when added to the display list. The _root property is now relative to each SWF loaded in the movie and can be accessed through the root property when a display object is added to the display list. The stage property can be used often in the same way you used to use the _root property to evaluate properties of the main timeline. The stage property is available to any display object when added to the display list.
 
 
Handling depths
The swapDepths and getNextHighestDepth methods no longer exist in ActionScript 3. Instead you'll use the DisplayObjectContainer methods associated with a movie clip container added to the display list. The terminology in ActionScript 3 is based on the display object's "index" in the list of child objects, instead of the concept of "depth."
 
For example, to send the myInstance clip to the top of the stacking order, use the following code:
 
setChildIndex(myInstance, numChildren - 1);
In the example above, the setChildIndex method and numChildren property are part of the DisplayObjectContainer API in the timeline to which the code is attached. The list of index (depth) numbers starts at 0 at the bottommost object and ascends to the value equaling numChildren - 1. In ActionScript 3 referencing any index above the numChildren - 1 value produces an error.
 
 
Using the drawing API
As with other changes to the MovieClip API, the drawing API has been moved to the graphics property of a display object. Other than its new location, the process for using it is the same—with a few noticeable enhancements. Some of my favorite new features include the drawRect and drawEllipse shortcut commands.
 
The following code shows how to dynamically draw a rectangle and then apply the rectangle as a mask to another instance. The mask object has no timeline, so it is created as a sprite instead of a movie clip:
 
import flash.display.Sprite; // Create mask var maskArea:Sprite = new Sprite(); maskArea.graphics.beginFill(0xFF0000); maskArea.graphics.drawRect(-29.5, -22.5, 59, 46); maskArea.graphics.endFill(); addChild(maskArea); // Apply mask myInstance.mask = maskArea;
The changes related to working with the display list offer many exciting new options for configuring your visual content. Check out the Display section of the ActionScript 3 Developer's Guide for more information.
 

 
Working with events

The following sections describe the standardized event handling model in ActionScript 3.
 
 
All events are handled the same way
Events have evolved in ActionScript 3. The event handling metaphor common to ActionScript 2 components has become part of all display objects in ActionScript 3. The big picture is that all objects in ActionScript now share a common event model. Along with standardization in ActionScript 3 comes a few changes to how event handler functions work. In the new model, the addEventListener method expects a function reference for the listener instead of an object or a function reference. In ActionScript 2 it was common to use an object as a container for a number of event handler functions, but in ActionScript 3 listeners appear as functions per event or as functions containing switch statements to handle multiple events.
 
The following code illustrates how a mouse event handler is assigned to a button:
 
import flash.events.MouseEvent; function clickHandler(event:MouseEvent):void { // Handle event here... } my_btn.addEventListener(MouseEvent.CLICK, clickHandler);
The code above first imports the MouseEvent class for data typing. The clickHandler function is the event handler that responds to the event notification. The addEventListener method registers the event handler with the object broadcasting the event.
 
 
Some events flow through the display list
Events for visual objects residing on the display list flow through the display list on the way to and from the target object. There are three phases to event propagation, and these phases allow objects other than the target object to receive the event. For example, consider a button in a movie clip on the main Timeline. If you click that button, the CLICK event travels from the Stage through the movie clip to the button, and then back up through the movie clip to the Stage. This structure allows you to associate the listener with the button (in which case you'll just receive an event from the button) or on the movie clip container (which would allow you to receive the click events from any number of buttons within the container). You could also place the listener on the Stage and receive CLICK events from anywhere in the movie. The ability to listen for events in this way opens up many possibilities for handling the event flow.
 
When setting up initialization code that requires access to the display list, you can use the ADDED_TO_STAGE event to perform the initialization at the correct time. For example:
 
import flash.event.Event; function addedToStageHandler(event:Event):void { // Initialization code goes here... } addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
Remember you might not always add the object to the display list immediately after instantiating it. Using the code above will allow you to initialize using the Stage without causing timing errors.
 
 
Using the currentTarget event property and target event property
The event handler function receives an event object with information about the event. In the ActionScript 2 component event structure you could always count on the target property as being a reference back to the object which broadcast the event. In ActionScript 3, the target property of the event object may not reference that object.
 
I found that assigning my listener directly to the target object and using the currentTarget event property is often the most reliable way to work with the structures I'm building; for example:
 
import flash.events.MouseEvent; function clickHandler(event:MouseEvent):void { // Do something on click... switch(event.currentTarget.name) { case "my_btn1": // do something... Break; case "my_btn2": // do something... Break; case "my_btn3": // do something... Break; } } my_btn1.addEventListener(MouseEvent.CLICK, clickHandler); my_btn2.addEventListener(MouseEvent.CLICK, clickHandler); my_btn3.addEventListener(MouseEvent.CLICK, clickHandler);
If you want to use the target property instead of currentTarget, be sure to notice the extra parameters associated with the addEventListener method. I discovered with ActionScript 3 that the target property was sometimes empty because the event system was deleting the reference to the target before it was sent to my event handler. To resolve this issue I changed the garbage-collection settings by adjusting the optional parameters that appear at the end of the addEventListener method. For example:
 
import flash.events.MouseEvent; function clickHandler(event:MouseEvent):void { // Do something on click... switch(event.target.name) { case "my_btn1": // do something... Break; case "my_btn2": // do something... Break; case "my_btn3": // do something... Break; } } addEventListener(MouseEvent.CLICK,clickHandler,false,0,true);
The last parameter is useWeakReference, and in the code above it is set to true. A strong reference prevents the listener from being garbage-collected. Therefore, setting this parameter to false causes the event system to not garbage-collect the reference to the event's target.
 
The event structure in ActionScript 3 is the key to synchronizing content in your movie and responding to user interactivity in the correct timing. Check out the Handling events section of the ActionScript 3 Developer's Guide for more information.
 

 
Loading data, content, and symbol instances

The following sections cover updates to loading images, server data, instances, and URLs.
 
 
Loading images and SWFs
Loading images and SWF files is no longer handled using the loadMovie method or MovieClipLoader class. Instead, use the URLRequest class and the Loader class to accomplish the same task.
 
The following code shows the bare bones of an image loader script:
 
import flash.display.Loader; import flash.net.URLRequest; var request:URLRequest = new URLRequest("img/image1.jpg"); var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded); loader.load(request); addChild(loader); function onImageLoaded(event:Event):void { // Center the image on stage loader.x = (stage.stageWidth – loader.content.width) / 2; loader.y = (stage.stageHeight – loader.content.height) / 2; }
Note that the loaded image is stored in the Loader instance's content property. Once the image is loaded, you can manipulate the Loader instance or the content property to adjust the image.
 
 
Loading server data
The following example illustrates how to call a server-side script and then respond to the completion of the data loading process:
 
import flash.display.URLLoader; import flash.net.URLRequest; import flash.events.Event; var loader:URLLoader = new URLLoader(); loader.load(new URLRequest("http://mysite.com/cgi/get_text.php")); function onDataHandler(event:Event):void { var result:String = String(loader.data); // add your code here... } loader.addEventListener(Event.COMPLETE, onDataHandler);
This code calls a script on a server and captures the data returned using the COMPLETE event of the URLLoader. You can use the URLVariables class to add GET or POST variables to the URLRequest.
 
 
Loading symbols explicitly
The attachMovie method and linkage identifiers no longer exist in ActionScript 3. Instead you can attach symbols from the library using one of two methods. Both routes require that you turn on the Export for ActionScript option in the Symbol Properties dialog box for the target symbol and enter a name in the Class field.
 
When the class name associated with a symbol is explicitly known, the following code pattern is used:
 
var myInstance = new MyClassName(); addChild(myInstance);
Note: All instances are created using the new keyword in ActionScript 3. If you've activated the Export for ActionScript object on any element in the Library (movie clip, button, sound, bitmap, etc.), you'll use the new keyword along with the class name to create the instance.
 
 
Loading symbol instances dynamically
Using the new keyword is easy and a great scripting convention, but it only works if you explicitly know the name of the class you're trying to instantiate. When building templates, I find I'm often in a position where I try to instantiate a class whose name is being supplied dynamically through an XML string or a naming convention of some kind. In these situations I use the UILoader component to dynamically create instances of symbols.
 
When the name of the class is not explicitly known, you can drag a UILoader component to your Library and use the following approach:
 
import fl.containers.UILoader; // Load an instance dynamically var myInstance:UILoader = new UILoader(); myInstance.scaleContent = false; myInstance.source = "myClassName"; addChild(myInstance);
Note: This code works well for loading display objects such as bitmaps and movie clips. For loading sounds from the library, you have to explicitly know the class names.
 
If you'd rather not work with the UILoader component, you can use the following ActionScript to instantiate a symbol by name:
 
var myClass:Class = stage.loaderInfo.applicationDomain.getDefinition("myClassName") as Class; var myInstance:MovieClip = new myClass() as MovieClip; addChild(myInstance);
This code retrieves the class from the Library by name and allows you to instantiate it as a generic Class object. This approach can also work well when you need to instantiate symbols from other SWFs loaded into your movie.
 
 
Loading a URL
The getURL method no longer exists in ActionScript 3. To call a URL, you will need to create a URLRequest instance and then call the navigateToUrl method. The following try..catch statement illustrates the error handling capabilities of ActionScript 3:
 
import flash.net.*; var url:String = "http://www.adobe.com"; var request:URLRequest = new URLRequest(url); try { navigateToURL(request); } catch (e:Error) { // Handle error... }
Notice that the script imports the flash.net package which contains the URLRequest class and navigateToURL method. The try..catch statement allows you to handle the error if the URL doesn't load.
 
Check out the ActionScript 3 Developer's Guide for more information on working with rich media and network communication.
 

 
Working with XML

The following sections cover updates to the XML class in ActionScript 3.
 
 
Loading XML
The XML class no longer contains loading functionality. It is purely used for manipulating an XML structure. To load XML, you follow the same process as calling a server-side script; use the URLReqest and URLLoader classes.
 
The following example illustrates how to load an XML file and then respond to the completion of the data loading process:
 
import flash.display.URLLoader; import flash.net.URLRequest; import flash.events.Event; var loader = new URLLoader(); loader.load(new URLRequest("conf/settings.xml")); function onDataHandler(event:Event):void { if((event.target as URLLoader) != null ) { var settingsXML = new XML(loader.data); } } loader.addEventListener(Event.COMPLETE, onDataHandler);
Notice the use of the as keyword in the event handler function above. In ActionScript 3 the as keyword can be used to cast an object as a related data type. This is handy in cases where you receive a reference to an object but the reference isn't necessarily of the same data type, or in cases where you want to test to see if an object evaluates to a certain data type. For example, in the code above, you can check to see if event.target is a URLLoader by using the as keyword. If the reference is null, it's not a URLLoader. You can also use the is keyword if you simply need to test whether an object "is" a specific data type—the difference being that the as keyword returns a data typed object or null whereas the is keyword returns true or false. This type of validation is a good way to avoid runtime errors.
 
 
Writing XML directly in ActionScript
A great new feature in ActionScript 3 is the ability to write XML directly in an ActionScript statement. The following example shows a variable containing XML written in ActionScript:
 
var books:XML = <books> <book category="1"> <title>Book 1</title> <author>Author 1</author> </book> <book category ="2"> <title>Book 2</title> <author>Author 2</author> </book> </books>
 
Working with XMLList objects using the dot syntax
Compared to ActionScript 2, the ActionScript 3 XML class is far easier to work with because you can access the nodes in much the same way you access properties within a standard object. Using dot notation and the XMLList methods, you can easily retrieve information. An XMLList is a new class that represents a list of children within a node. Working with the XMLList is somewhat similar to working with a standard array.
 
The following example shows how to loop through the book XMLList within the books XML object:
 
for each(var elem in books.book){ trace('Author: '+elem.author+', Title: '+elem.title+', Category: '+elem.@category); }
 
Filtering XML without looping
Another great feature of working with XML in ActionScript 3 is the ability to filter the XMLList objects without looping. Instead you can use additions to the XML handling operators and let Adobe Flash Player do the work.
 
The following example shows how to filter the book XMLList to return a new XMLList containing only books with a category attribute of 2:
 
var filteredList:XMLList = books.book.(@category=="2");
Notice the use of the @ operator to access the attribute and the use of the conditional statement to filter the results.
 
 
Accessing XML properties
While working with the new XML syntax is easier than ever, it's important to note that the content of a node isn't necessarily evaluated to a String data type. This can cause problems when copying data or comparing strings in a conditional statement. You can cast the node values as Strings or use the text method of the element.
 
The following example retrieves the author from the second book as a text string:
 
var author2:String = books.book[1].author.text();
Check out the Working with XML section of the ActionScript 3 Developer's Guide for more information about XML in ActionScript 3.
 

 
Building object classes in ActionScript 3

The following sections cover the package keyword and general changes to working with the ActionScript language.
 
 
The package keyword
The structure of an ActionScript 3 class is not very different from an ActionScript 2 class. Perhaps the biggest structural difference is the use of the package keyword to start the ActionScript 3 file.
 
If you save a class named myClass into a folder named myCode, then the structure of the class file looks like this:
 
package myCode { import flash.display.MovieClip; public class myClass extends MovieClip { function myClass(){ // write out class as usual from here... } } }
 
New class attribute keywords
In addition to the new package keyword, ActionScript 3 classes allow you to use a few other keywords to create encapsulation in your classes in a more specific way.
 
New class attribute keywords include:
 
  • final
  • internal
  • native
  • override
  • protected
The protected keyword works in the same way that the private keyword does in ActionScript 2. It allows you to create variables and functions that are accessible to subclasses, but inaccessible to external objects. The private keyword now makes variables truly private and only accessible within the class. The override keyword is now required when overriding a function in a subclass.
 
 
Using a document class
The ActionScript 3 FLA file format allows you to assign an ActionScript class to the main Timeline. A class assigned to the main Timeline is called a document class. This feature allows FLA files to completely externalize ActionScript code to a class package.
 
To assign a document class, simply select the Stage to access its properties in the Property inspector, and then enter the class name in the Document class field (see Figure 1).
 
ActionScript 3 class assigned to the main Timeline of an ActionScript 3 FLA file
Figure 1. ActionScript 3 class assigned to the main Timeline of an ActionScript 3 FLA file.
 
Assigning classes to movie clip symbols
ActionScript 3 FLA files add two new fields to the symbol properties: the Class and Base Class fields (see Figure 2). To assign a class to a symbol, you have to turn on the Export for ActionScript option and enter the name of the class in the Class field. In cases where you want to assign the class to multiple symbols, enter the class in the Base Class field (the Class field must remain unique).
 
ActionScript 3 class assigned to a symbol using the Class and Base Class fields in the symbol's properties
Figure 2. ActionScript 3 class assigned to a symbol using the Class and Base Class fields in the symbol's properties
Check out the Object-oriented programming in ActionScript section of the ActionScript 3 Developer's Guide for more details on ActionScript 3 classes.
 

 
Where to go from here

The topics covered in this article are the most important items that came to my attention as I learned ActionScript 3. For more information, visit the ActionScript Technology Center. See also the ActionScript 2 migration reference for complete details on the differences between ActionScript 2 to ActionScript 3.