Showcase and discover digital art at yex

Follow Design Stacks

Subscribe to our free newsletter to get all our latest tutorials and articles delivered directly to your inbox!

ActionScript Coding Conventions

ActionScript Coding Conventions

One of the most important aspects about programming is consistency, whether it relates to variable naming schemes, formatting code, 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.

Keeping Your ActionScript Code in One Place

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:

  • Code is easy to find in a potentially complex source file.
  • Code is easy to debug.

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.”

Attaching Code to Objects

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:

  • ActionScript code that is attached to objects is difficult to locate, and the FLA files are difficult to edit.
  • ActionScript code that is attached to objects is difficult to debug.
  • ActionScript code that is written on a timeline or in classes is more elegant and easier to build upon.
  • ActionScript code that is attached to objects encourages poor coding style.
  • ActionScript code that is attached to objects forces students and readers to learn additional syntax as well as different coding styles that are often poor and limited.
  • Users typically have to relearn how to write functions and so on, on a timeline at a later date.

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.
};

Note: Using behaviors and screens sometimes involves attaching code to objects, so different practices apply when you use these features.

Handling Scope

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.

Avoiding Absolute Targets (‘_root’)

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.

Using ‘_lockroot’

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; 

Using the ‘this’ Keyword

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.

About Scope in Classes

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.

Structuring a Class File

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:

  1. Add documentation comments that include a general description of the code, in addition to author information and version information.
  2. Add your import statements (if applicable).
  3. Write a class declaration, or interface declaration, such as the following:

    UserClass{...} 
  4. Include any necessary class or interface implementation comments. In this comment, add information that is pertinent for the entire class or interface.
  5. Add all your static variables. Write the public class variables first and follow them with private class variables.
  6. Add instance variables. Write the public member variables first, and follow them with private member variables.
  7. Add the constructor statement, such as the one in the following example:

    public function UserClass(username:String, 
    password:String) {...}
  8. Write your methods. Group methods by their functionality, not by their accessibility or scope. Organizing methods this way helps to improve the readability and clarity of your code.
  9. Write the getter/setter methods into the class file.

Guidelines for Creating a Class

Remember the following guidelines when you create a class file:

  • Place only one declaration per line.
  • 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.

  • Initialize local variables when they are declared. A class’s properties should only be initialized in the declaration if the initializer is a compile-time constant.
  • Declare variables before you first use them. This includes loops.
  • 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;
    }
  • Make a method or property public only if it needs to be public for a reason. Otherwise, make your methods and properties private.
  • 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.

  • Set most member variables to private unless you have a good reason for making them public. From a design standpoint, it is much better to make member variables private and allow access to those variables through a group of getter/setter functions only.

Using the ‘this’ Prefix in Class Files

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.

About Initialization

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. This class sets the initial values of m_username and m_password to empty strings:

class User {
private var m_username:String = "";
private var m_password:String = "";
function User(username:String, password:String) {
this.m_username = username;
this.m_password = password;
}
}

Delete variables or make variables null when you no longer need them. Setting variables to null can still enhance performance. This process is commonly called garbage collection. Deleting variables helps optimize memory use during runtime, because unneeded assets are removed from the SWF file. It is better to delete variables than to set them to null.

Note: Flash Player 8 has made improvements in garbage collection within Flash Player.

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");
}
};
prodXml.load("products.xml");
init = true;
}

Use ‘trace’ Statements

Use trace statements in your documents to help you debug your code while authoring the FLA file. For example, by using a trace statement and for loop, you can see the values of variables in the Output panel, such as strings, arrays, and objects, as the following example shows:

var dayArr: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.

The Debugger tool is also useful for debugging ActionScript code.

About the ‘super’ Prefix

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.

Avoid the ‘with’ Statement

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 a timeline of the SWF file.

It is easier to follow what is happening in your code if you explicitly specify the variables scope, instead of relying on the with statement. The following example shows a slightly longer, but better, ActionScript example that specifies the variables scope:

this.attachMovie("circleClip", "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) {
lineStyle(2, 0x000000, 100);
beginFill(0xFF0000, 100);
moveTo(0, 0);
lineTo(300, 0);
lineTo(300, 200);
lineTo(0, 200);
lineTo(0, 0);
endFill();
}

If you wrote each lineTo or curveTo method with a fully qualified instance name, the code would quickly become cluttered and difficult to read and debug.

About Using Functions

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;
var randomMonth:Number = Utils.randomRange(0, 11);
var min:Number = Utils.arrayMin([3, 3, 5, 34, 2, 1, 1, -3]);
var max:Number = Utils.arrayMax([3, 3, 5, 34, 2, 1, 1, -3]);
trace("month: "+randomMonth);
trace("min: "+min);
trace("max: "+max);

About Stopping Code Repetition

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.

Comments