Adobe
flashthusiast.com
ActionScript coding conventions are very important for Macromedia Flash designers and developers to ensure that code and applications are structured in a way that is intuitive and beneficial to themselves as well as other people working on the same project. This is particularly important with long code files. When you follow coding conventions, everyone on the design and development team can understand the code and can work more efficiently. This document helps formalize the ActionScript coding process.
The sections in this article outline best practices for writing ActionScript. Some sections of Flash Help (Help > Getting Started in Flash) or the Flash 8 LiveDocs are helpful as well: Learning ActionScript 2.0 in Flash and ActionScript 2.0 Language Reference.
Note: For information about using Flash 8 and organizing FLA files, see Flash 8 Best Practices. It complements this document.
The following guidelines encourage consistency for people learning how to write ActionScript code. Adopt best practices at all times, whether you are a designer or developer, or working alone or as part of a team:
Note: If you are still using Flash MX Professional 2004 and not Flash Professional 8, please see the previous version of this article.
These guidelines relate to the following software:.
This section describes how to use comments in your code. Comments document the decisions you make in the code, answering both how and why. For example, you might describe a workaround in comments. Another developer would be able to find the related code easily for updating or fixing. And finally, the issue might be addressed in a future version of Flash or Flash Player, hence the workaround would no longer be necessary.
Using comments consistently in your ActionScript 2.0 code allows you to describe complex areas of code or important interactions that are not otherwise clear. Comments must clearly explain the intent of the code and not just translate the code. If something is not readily obvious in the code, add comments to it.
If you use the Auto Format tool with your code, you will notice that trailing comments move to the next line. You can add these comments after you format your code, or you must modify the comment's new placement after you use the Auto Format tool.
For information on trailing comments, see Trailing Comments in Flash Help or the Flash 8 LiveDocs (Learning ActionScript 2.0 in Flash > Syntax and Language Fundamentals > About Language Punctuators > About Comments > Trailing Comments).
For information on using comments in classes, see the next section, "Adding Comments to Classes."
Use the following guidelines when you add comments to your code:
/*and
*/) for multiline comments and single-line comments (
//) for short comments. You can also use a trailing comment on the same line as the ActionScript code if necessary.
=) or asterisks (
*). Instead, use white space to separate your comments from ActionScript code.
Note: If you use the Auto Format tool to format ActionScript, you remove the white space. Remember to add it back or use single-line comments (
//) to maintain spacing; these lines are easy to remove after you format your code.
Note: Using comments is most important in ActionScript code that is intended to teach an audience. For example, add comments to your code if you are creating sample applications for the purpose of teaching Flash, or if you are writing tutorials about ActionScript code.
The two kinds of comments in a typical class or interface file are documentation comments and implementation comments.
Note: Documentation and implementation comments are not formally represented in the ActionScript language. However, they are commonly used by developers when writing class and interface files.
You use documentation comments to describe the code's specifications, but not the implementation. You use implementation comments to comment out code or to comment on the implementation of particular sections of code. Documentation comments are delimited with
/** and
*/, and implementation comments are delimited with
/* and
*/.
Use documentation comments).
Start classes with a standard comment, which uses the following format:
/** User class version 1.2 3/21/2006 Copyright Adobe Systems, Inc. */
After the documentation comments, declare the class. Implementation comments should directly follow the declaration.
Note: Don't include comments that do not directly relate to the class that's being read. For example, don't include comments that describe the corresponding package.
Use block, single-line, and trailing comments within the body of your class to comment on your ActionScript code.
One of the most important aspects about programming is consistency, whether it relates to variable naming schemes (covered in the earlier section, "Naming Conventions"), formatting code (covered in the later section, "Formatting ActionScript Syntax"), or coding standards and the placement of your ActionScript 2.0 code, which is covered in this section. You dramatically simplify code debugging and maintenance if your code is organized and adheres to standards.
Whenever possible, put your ActionScript 2.0 code in a single location, such as in one or more external ActionScript files or on Frame 1 of the Timeline (when placed on the timeline, the code is called a frame script).
If you put your ActionScript code in a frame script, put the ActionScript code on the first or second frame on the Timeline, in a layer called Actions, which is the first or second layer on the Timeline. Sometimes you might create two layers—an acceptable practice—for ActionScript to separate functions. Some Flash applications do not always put all your code in a single place (in particular, when you use screens or behaviors).
Despite these rare exceptions, you can usually put all your code in the same location. The following are the advantages of placing your ActionScript in a single location:
One of the most difficult parts of debugging a FLA file is finding all the code. After you find all the code, you must figure out how it interacts with other pieces of code along with the FLA file. If you put all your code in a single frame, it is much easier to debug because it is centralized, and these problems occur less frequently. For information on attaching code to objects (and decentralizing your code), see the next section, "Attaching Code to Objects." For more information on behaviors and decentralized code, see the section "Behaviors Conventions" in Flash 8 Best Practices.
You must avoid attaching ActionScript code to objects (such as button or movie clip instances) in a FLA file, even in simple or prototype applications. Attaching code to an object means that you select a movie clip, component, or button instance, open the ActionScript editor (the Actions panel or Script window), and add ActionScript code by using the
on() or
onClipEvent() handler functions.
This practice is strongly discouraged for the following reasons:
Some Flash users might say it is easier to learn ActionScript by attaching code to an object. Some also say it might be easier to add simple code, or write about or teach ActionScript this way. However, the contrast between two styles of coding (code placed on objects, and frame scripts) can be confusing to developers who are learning ActionScript and should be avoided. Also, users who learn how to write code attached to objects often have to relearn how to place the equivalent code as a frame script at a later date. This is why consistency throughout the learning process, by learning how to write frame scripts, has advantages.
Attaching ActionScript code to a button called
myBtn appears as follows. Avoid this method:
on (release) { // Do something. }
Note: However, placing the equivalent ActionScript code on a timeline appears as follows:
// good code myBtn.onRelease = function() { // Do something. };
For more information, see Syntax and Language Fundamentals in Flash Help or the Flash 8 LiveDocs (Learning ActionScript 2.0 in Flash > Syntax and Language Fundamentals).
Note: Using behaviors and screens sometimes involves attaching code to objects, so different practices apply when you use these features. For more information on behaviors and decentralized code, see the section "Behaviors Conventions" in Flash 8 Best Practices. For more information on screens, see the section "Screens Conventions."
Scope is the area where the variable is known and can be used in a SWF file, such as on a timeline, globally across an application, or locally within a function. Typically, you can reference scope in more than one way when you write code. Using scope correctly means that you can create portable and reusable ActionScript code, and you don't risk breaking your applications as you build new modules.
It is important to understand the difference between the global and root scopes. The root scope is unique for each loaded SWF file. The global scope applies to all timelines and scopes within SWF files. You use relative addressing rather than references to root timelines, because relative addressing makes your code reusable and portable.
You can use several methods to target instances that let you avoid using
_root; these methods are discussed later in this section. Avoid using
_root in ActionScript 2.0 because SWF files that load into other SWF files might not work correctly. The
_root identifier targets the base SWF file that is loading, not the SWF file using relative addressing instead of
_root. This issue limits code portability in SWF files that are loaded into another file, and, particularly, in components and movie clips. You can help resolve problems by using
_lockroot, but only use
_lockroot when necessary (such as when you are loading a SWF file but do not have access to the FLA file). For more information on using
_lockroot, see the next section, "Using _lockroot."
Use
this,
this._parent, or
_parent keywords rather than
_root, depending on where your ActionScript 2.0 code is located. The following example shows relative addressing:
myClip.onRelease = function() { trace(this._parent.myButton._x); };
All variables must be scoped, except for variables that are function parameters, and local variables. Scope variables relative to their current path whenever possible, using relative addressing, such as the
this property. For more information on using the
this property, see This Property in Flash Help or the Flash 8 LiveDocs (ActionScript 2.0 Language Reference > ActionScript Language Elements > Global Properties > This Property).
You can use
_lockroot to target content as a way to solve the scoping issues sometimes associated with the inappropriate use of
_root. Although this solves many problems with applications, consider
_lockroot as a work-around for problems caused by using
_root. If you experience problems loading content into a SWF file or a component instance, try applying
_lockroot to a movie clip that loads the content. For example, if you have a movie clip called
myClip loading content, and it stops working after it is loaded, try using the following code, which is placed on a timeline:
this._lockroot = true;
Whenever possible, use the
this keyword as a prefix instead of omitting the keyword, even if your code works without it. Use the
this keyword to learn when a method or property belongs to a particular class. For example, for a function on a timeline, you write ActionScript 2.0 code by using the following format:
circleClip.onPress = function() { this.startDrag(); }; circleClip.onRelease = function() { this.stopDrag(); };
For a class, use the following format to write code:
class User { private var username:String; private var password:String; function User(username:String, password:String) { this.username = username; this.password = password; } public function get username():String { return this.username; } public function set username(username:String):Void { this.username = username; } }
If you consistently add the
this keyword in these situations, your ActionScript 2.0 code will be much easier to read and understand.
When you port code to ActionScript 2.0 classes, you might have to change how you use the
this keyword. For example, if you have a class method that uses a callback function (such as the LoadVars class's
onLoad method), it can be difficult to know if the
this keyword refers to the class or to the LoadVars object. In this situation, you might need to create a pointer to the current class, as the following example shows:
class Product { private var m_products_xml:XML; // Constructor // targetXmlStr contains the path to an XML file function Product(targetXmlStr:String) { /* Create a local reference to the current class. Even if you are within the XML's onLoad event handler, you can reference the current class instead of only the XML packet. */ var thisObj:Product = this; // Create a local variable, which is used to load the XML file. var prodXml:XML = new XML(); prodXml.ignoreWhite = true; prodXml.onLoad = function(success:Boolean) { if (success) { /* If the XML successfully loads and parses, set the class's m_products_xml variable to the parsed XML document and call the init function. */ thisObj.m_products_xml = this; thisObj.init(); } else { /* There was an error loading the XML file. */ trace("error loading XML"); } }; // Begin loading the XML document prodXml.load(targetXmlStr); } public function init():Void { // Display the XML packet trace(this.m_products_xml); } }
Because you are trying to reference the private member variable within an
onLoad handler, the
this keyword actually refers to the
prodXml instance and not to the
Product class, which you might expect. For this reason, you must create a pointer to the local class file so that you can directly reference the class from the
onLoad handler.
You create classes in separate ActionScript 2.0 files that are imported into a SWF file when it is compiled.
You create classes in separate ActionScript 2.0 files that are imported into a SWF file when you compile an application. To create a class file, you write code that can have a certain methodology and ordering. This methodology is discussed in the following sections.
The following conventions for structuring a class file show how you can order parts of a class to increase the efficiency and improve the readability of your code.
To structure a class file, use the following elements:
Write a class declaration, or interface declaration, such as the following:
UserClass{...}
Add the constructor statement, such as the one in the following example:
public function UserClass(username:String, password:String) {...}
Remember the following guidelines when you create a class file:
Don't place multiple declarations on a single line. For example, format your declarations as shown in the following example:
var prodSkuNum:Number; // Product SKU (identifying) number var prodQuantityNum:Number; // Quantity of product
This example shows better form than putting both declarations on a single line. Place these declarations at the beginning of a block of code.
Avoid using local declarations that hide higher-level declarations. For example, don't declare a variable twice, as the following example shows:
var counterNum:Number = 0; function myMethod() { for (var counterNum:Number = 0; counterNum<=4; counterNum++) { // statements; } }
This code declares the same variable inside an inner block, which is a practice to avoid.
Don't assign many variables to a single value in a statement. Follow this convention because otherwise your code is difficult to read, as the following ActionScript code shows:
playBtn.onRelease = playBtn.onRollOut = playsound;
or
class User { private var m_username:String, m_password:String; }
Don't overuse getter/setter functions in your class file. Getter/setter functions are excellent for a variety of purposes; however, overuse might indicate that you could improve upon your application's architecture or organization.
For more information, see About Getter and Setter Methods in Flash Help or the Flash 8 LiveDocs (Learning ActionScript 2.0 in Flash > Classes > About working with custom classes in an application > About getter and setter methods).
Use the
this keyword as a prefix within your classes for methods and member variables. Although it is not necessary, it makes it easy to tell that a property or method belongs to a class when it has a prefix; without it, you cannot tell if the property or method belongs to the superclass.
You can also use a class name prefix for static variables and methods, even within a class. This helps qualify the references you make. Qualifying references makes for readable code. Depending on what coding environment you are using, your prefixes might also trigger code completion and hinting. The following code demonstrates prefixing a static property with a class name:
class Widget { public static var widgetCount:Number = 0; public function Widget() { Widget.widgetCount++; } }
Note: You don't have to add these prefixes, and some developers feel it is unnecessary. Adobe recommends that you add the
this keyword as a prefix, because it can improve readability and it helps you write clean code by providing context.
For the initial values for variables, assign a default value or allow the value of
undefined, as the following class example shows. When you initialize properties inline, the expression on the right side of an assignment must be a compile-time constant. That is, the expression cannot refer to anything that is set or defined at runtime. Compile-time constants include string literals, numbers, Boolean values, null, and undefined, as well as constructor functions for the following top-level classes: Array, Boolean, Number, Object, and String. the upcoming section, "Optimizing Your Code."
Note: Flash Player 8 has made improvements in garbage collection within Flash Player.
For information on naming variables, see the earlier section, "Naming Variables." For more information on deleting objects, see Delete Statement in Flash Help or the Flash 8 LiveDocs (ActionScript 2.0 Language Reference > ActionScript Language Elements > Statements > Delete Statement).
Note: One of the easiest ways to initialize code by using ActionScript 2.0 is to use classes. You can encapsulate all your initialization for an instance within the class's constructor function, or abstract it into a separate method, which you would explicitly call after the variable is created, as the following code shows:
class Product { function Product() { var prodXml:XML = new XML(); prodXml.ignoreWhite = true; prodXml.onLoad = function(success:Boolean) { if (success) { trace("loaded"); } else { trace("error loading XML"); } }; prodXml.load("products.xml"); } }
The following code could be the first function call in the application, and the only one you make for initialization. Frame 1 of a FLA file that is loading XML might use code that is similar to the following ActionScript:
if (init == undefined) { var prodXml:XML = new XML(); prodXml.ignoreWhite = true; prodXml.onLoad = function(success:Boolean) { if (success) { trace("loaded"); } else { trace("error loading XML"); } }; prodXmlArr:Array = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"]; var numOfDays:Number = dayArr.length; for (var i = 0; i<numOfDays; i++) { trace(i+": "+dayArr[i]); }
This displays the following information in the Output panel:
0: sun 1: mon 2: tue 3: wed 4: thu 5: fri 6: sat
Using a
trace statement is an efficient way to debug your ActionScript 2.0. You can remove your
trace statements when you publish a SWF file, which makes minor improvements to playback performance. Before you publish a SWF file, open Publish Settings and select Omit Trace Actions on the Flash tab.
For more information on using a
trace, see Trace Function in Flash Help or the Flash 8 LiveDocs (ActionScript 2.0 Language Reference > ActionScript Language Elements > Global Functions > Trace Function).
The Debugger tool is also useful for debugging ActionScript code. For more information, see Debugging Applications in Flash Help or the Flash 8 LiveDocs (Learning ActionScript 2.0 in Flash > Debugging Applications).
If you refer to a method in the parent class, prefix the method with
super so that other developers know from where the method is invoked. In the following example, you create two classes. You use the
super keyword in the Socks class to call functions in the parent class (Clothes). Although both the Socks and Clothes classes have a method called
getColor(), using
super lets you specifically reference the base class's methods and properties. Create a new AS file called Clothes.as, and enter the following code:
class Clothes { private var color:String; function Clothes(paramColor) { this.color = paramColor; trace("[Clothes] I am the constructor"); } function getColor():String { trace("[Clothes] I am getColor"); return this.color; } function setColor(paramColor:String):Void { this.color = paramColor; trace("[Clothes] I am setColor"); } }
Create a new class called Socks that extends the Clothes class, as shown in the following example:
class Socks extends Clothes { private var color:String; function Socks(paramColor:String) { this.color = paramColor; trace("[Socks] I am the constructor"); } function getColor():String { trace("[Socks] I am getColor"); return super.getColor(); } function setColor(paramColor:String):Void { this.color = paramColor; trace("[Socks] I am setColor"); } }
Then create a new AS or FLA file and enter the following ActionScript in the document:
import Socks; var mySock:Socks = new Socks("maroon"); trace(" -> "+mySock.getColor()); mySock.setColor("Orange"); trace(" -> "+mySock.getColor());
The following result is displayed in the Output panel:
[Clothes] I am the constructor [Socks] I am the constructor [Socks] I am getColor [Clothes] I am getColor -> maroon [Socks] I am setColor [Socks] I am getColor [Clothes] I am getColor -> Orange
If you forgot to put the
super keyword in the Socks class's
getColor() method, the
getColor() method could call itself repeatedly, which would cause the script to fail because of infinite recursion problems. The Output panel would display the following error if you didn't use the super keyword:
[Socks] I am getColor [Socks] I am getColor ... [Socks] I am getColor 256 levels of recursion were exceeded in one action list. This is probably an infinite loop. Further execution of actions has been disabled in this SWF file.
One of the more confusing concepts to understand for people learning ActionScript 2.0 is using the
with statement. Consider the following code that uses the
with statement:
this.attachMovie("circleClip", "circle1Clip", 1); with (circle1Clip) { _x = 20; _y = Math.round(Math.random()*20); _alpha = 15; createTextField("labelTxt", 100, 0, 20, 100, 22); labelTxt.text = "Circle 1"; someVariable = true; }
In this code, you attach a movie clip instance from the library and use the
with statement to modify its properties. When you do not specify a variable's scope, you do not always know where you are setting properties, so your code can be confusing. In the previous code, you might expect
someVariable to be set within the
circle1Clip movie clip, but it is actually set in aClip", "circle1Clip", 1); circle1Clip._x = 20; circle1Clip._y = Math.round(Math.random()*20); circle1Clip._alpha = 15; circle1Clip.createTextField("labelTxt", 100, 0, 20, 100, 22); circle1Clip.labelTxt.text = "Circle 1"; circle1Clip.someVariable = true;
An exception to this rule is, when you are working with the drawing API to draw shapes, you might have several similar calls to the same methods (such as
lineTo or
curveTo) because of the drawing API's functionality. For example, when you draw a simple rectangle, you need four separate calls to the
lineTo method, as the following code shows:
this.createEmptyMovieClip("rectangleClip", 1); with (rectangleClip) {.
Reuse blocks of code whenever possible. One way you can reuse code is by calling a function multiple times, instead of creating different code each time. Functions can be generic pieces of code; therefore, you can use the same blocks of code for slightly different purposes in a SWF file. Reusing code lets you create efficient applications and minimize the ActionScript 2.0 code that you must write, which reduces development time. You can create functions on a timeline, in a class file, or write ActionScript that resides in a code-based component, and reuse them in a variety of ways.
If you are using ActionScript 2.0, avoid writing functions on a timeline. When you use ActionScript 2.0, place functions into class files whenever possible, as the following example shows:
class Circle { public function area(radius:Number):Number { return (Math.PI*Math.pow(radius, 2)); } public function perimeter(radius:Number):Number { return (2 * Math.PI * radius); } public function diameter(radius:Number):Number { return (radius * 2); } }
Use the following syntax when you create functions:
function myCircle(radius:Number):Number { //... }
Avoid using the following syntax, which is difficult to read:
myCircle = function(radius:Number):Number { //... }
The following example puts functions into a class file. This is a best practice when you choose to use ActionScript 2.0, because it maximizes code reusability. To reuse the functions in other applications, import the existing class rather than rewrite the code from scratch, or duplicate the functions in the new application.
class mx.site.Utils { static function randomRange(min:Number, max:Number):Number { if (min>max) { var temp:Number = min; min = max; max = temp; } return (Math.floor(Math.random()*(max-min+1))+min); } static function arrayMin(numArr:Array):Number { if (numArr.length == 0) { return Number.NaN; } numArr.sort(Array.NUMERIC | Array.DESCENDING); var min:Number = Number(numArr.pop()); return min; } static function arrayMax(numArr:Array):Number { if (numArr.length == 0) { return undefined; } numArr.sort(Array.NUMERIC); var max:Number = Number(numArr.pop()); return max; } }
You might use these functions by adding the following ActionScript to your FLA file:
import mx.site.Utils;); trace("max: "+max);
The
onEnterFrame event handler is useful because Flash can use it to repeat code at the frame rate of a SWF file. However, limit the amount of repetition that you use in a Flash file as much as possible so that you do not affect performance. For example, if you have a piece of code that repeats whenever the playhead enters a frame, it is processor intensive. This behavior can cause performance problems on computers that play the SWF file. If you use the
onEnterFrame event handler for any kind of animation or repetition in your SWF files, delete the
onEnterFrame handler when you finish using it. In the following ActionScript 2.0 code, you stop repetition by deleting the
onEnterFrame event handler:
circleClip.onEnterFrame = function() { circleClip._alpha -= 5; if (circleClip._alpha<=0) { circleClip.unloadMovie(); delete this.onEnterFrame; trace("deleted onEnterFrame"); } };
Similarly, limit the use of
setInterval, and remember to clear the interval when you finish using it to reduce processor requirements for the SWF file.
If.
ActionScript 2.0 compiles to ActionScript 1.0 bytecode when you publish your applications, so you can target Flash Player 6, 7, or 8 while working with ActionScript 2.0.
Remember the following guidelines when you optimize your code:
eval()function or array access operator. Often, setting the local reference once is preferable and more efficient.
Assign the
Array.length to a variable before a loop.]); }
instead of:
var fontArr:Array = TextField.getFontList(); for (var i:Number = 0; i < fontArr.length; i++) { trace(fontArr[i]); }
setInterval()function).
varkeyword when declaring a variable. + "\n"); + "\n" ); //good ("size is " + foo + "\n");;
Note: You can control auto-indentation and indentation settings by selecting Edit > Preferences (Windows) or Flash > Preferences (Macintosh), and then selecting the ActionScript tab.
Use the following guidelines when you write conditional statements:
if,
else..if, and
if..elsestatements
{}).
You can write
while statements using the following format:
while (condition) { // statements }
You can write
do-while statements using the following format:
do { // statements } while (condition););
Follow these rules when writing
switch statements: A in the following code example).
Your statement should include a comment in the
break statement.
For more information about using ActionScript, please see the following resources:.