Variables and Properties

A variable is a named element you can use to store data or a reference to data. You can assign values to and read values from a variable.

When you want to work with a variable, the first thing you’ll need to do is declare it. Declaring a variable allocates memory for it and tells the application that the variable exists. You can declare a variable using the var keyword as follows:

var variableName;

The var keyword is followed by the name of the variable. Variable names in ActionScript are arbitrary, but they must follow a few simple rules:

  • The variable name can consist only of letters, numbers, dollar signs, and underscores.

  • The variable name must not start with a number.

By convention, all ActionScript variables use initial lowercase letters rather than initial uppercase letters. The following declares a variable called userName:

var userName;

Although you can declare a variable without a data type, it’s always recommended that you declare a variable with a data type. You can add a data type to the variable declaration using post-colon syntax as follows:

var variableName:DataType;

Note

If you declare a variable without a data type, Flash Player allows any data to be assigned to the variable regardless of the type. The result is that there is no runtime type-checking for the variable, and there is no compile-time or runtime optimization because the type is not known ahead of time.

The data type determines the kind of data you can store in the variable. There are many data types, ranging from simple strings and numbers to reference types (such as arrays), and all the types defined by the Flex framework (e.g., TextInput, Button, etc.). There are far too many data types to list comprehensively here (especially because you can define custom data types). However, some of the most common core data types are String, Number, Int, Uint, Boolean, Date, and Array, as defined in Table 4-1.

Table 4-1. Common data types and their descriptions

Data type

Description

String

One or more characters, including all Unicode characters

Number

Any numeric value, including floating-point numbers

Int

Positive and negative integers and 0

Uint

Positive integers and 0

Boolean

True or false

Date

The date and time

Array

An index-ordered collection of data

When a variable is declared with a data type, you’ll receive errors if you attempt to assign an invalid value to the variable. Flex applications provide both compile-time and runtime type checking.

The following example declares the userName variable with the data type String:

var userName:String;

Once you’ve declared a variable, the next thing to do is to assign values using an assignment operator (an equals sign), as in the following example:

userName = "Flex User";

You can also combine a declaration and assignment into one line:

var userName:String = "Flex User";

When you want to retrieve a value from a variable, simply reference the variable in a statement or expression that expects that type of value. The next example assigns the value from the userName variable to the text property of a text input component:

textInput.text = userName;

Variables are placed within class methods (you can find more on method syntax in Methodsˮ later in this chapter). Variables declared outside methods are called properties, and they are scoped to the entire class. In most respects, variables and properties are the same. However, there is one key difference that shows up syntactically, which is simply a matter of scope. Here we describe the contrast between variable and property scope:

  • Variables declared within methods are scoped exclusively to those methods. That means you can't reference a variable outside the method in which it is declared.

  • Properties, on the other hand, have much greater scope. At a minimum, a property is accessible within the entire class. However, you can also opt to allow the property to be accessible outside the class with various settings called modifiers.

Classes define properties using quite a few possible modifiers. A property can be one of the following: public; private; protected; or internal.

public

The public modifier means the property is accessible outside the class (e.g., from an instance of the class).

private

The private modifier makes the property accessible only within the class.

protected

The protected modifier makes the property accessible only within the class and its subclasses.

internal

The internal modifier makes the property accessible only within the package.

Practically, you should always declare properties as private or protected. It is not a good idea to declare public properties because a class should always manage its state (the values of its properties). internal properties are a bad idea for the same reason.

You can declare properties in much the same way as you would declare variables using the var keyword. In addition, property names must follow the same rules as variable names. A common convention (and one used in this book) names private and protected properties with an initial underscore (_) to help distinguish them from local variables declared within methods. The following example declares a private property called _loader of type URLLoader:

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
  }
}

In addition to the public, private, protected, and internal modifiers, you can also combine these modifiers with the static modifier. The static modifier says that the property is directly accessible from the class rather than from instances. Static modifiers are used for many purposes, including design patterns such as the Singleton pattern. The following example adds a static private property called _instance of type Example:

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
    static private var _instance:Example;
  }
}

A concept related to properties is that of the constant. A constant is a container for data, much like a variable/property, except that once it has a value, you cannot change the value (hence the name, constant). You’ve likely seen constants in the Flash Player and Flex framework APIs. A few examples of constants are Event.COMPLETE, MouseEvent.CLICK, TimerEvent.TIMER, and Math.PI. Although not a requirement, most constants are declared as static, and most are also declared as public (unlike properties, constants aren’t part of a class’s state and can therefore be declared as public). To declare a constant, use the const keyword rather than var. By convention, constant names are all uppercase, as shown here:

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
    static private var _instance:Example;
    static public const TEST:String = "test constant";
  }
}

Methods

A method is a way to group together statements, give that group a name, and defer the execution of those statements until the method is called by its name. All method definitions must be placed within a class body, and they use the function keyword followed by the name of the method. Following the method name is a pair of parentheses enclosing any parameters that the method might accept. That is followed by a colon and the return type of the method. If the function does not return a value, the return type is declared as void. Following the return type declaration is the function definition enclosed in opening and closing curly braces. The following is a declaration for a function called test():

function test():void {
}

The test() method is declared so that it does not expect any parameters, and it does not expect to return a value. Currently, the test() method doesn’t do anything either. Next, add a few statements inside the function so that it does something:

function test():void {
  var message:String = "function message";
  trace(message);
}

Note

The trace() function writes text to an output such as a console or logfile. Chapter 18 discusses trace() and application debugging in more detail.

Now the test() method declares a variable called message, assigns a value to it (function message), and then uses trace() to output the value to the console (if debugging).

To call a method, use the method name followed by the function call operator (the parentheses). For example, if you want to call the test() method, you would use the following statement:

test();

Note

The preceding example assumes that test() is declared in the same MXML component or ActionScript class from which you are trying to call it. Otherwise, if you want to call a method that is defined in a different ActionScript class or MXML component, the method must be declared as public (see later in this section for more information on declaring methods as public) and you must use dot notation to call the method from an instance of the class or component in which the method is defined.

If you want to declare a method so that you can pass it parameters, you must declare the parameters within the parentheses as a comma-delimited list. The parameter declarations consist of the parameter name and post-colon data typing. The following example rewrites test() so that it expects two parameters (a and b):

function test(a:String, b:String):void {
  trace("Your message is " + a + " and " + b);
}

When you want to call a method with parameters, simply pass the values within the function call operator, as in the following example:

test("one", "two");

ActionScript does not allow overloading. That means you cannot have two methods with the same name but different signatures (different parameter lists). However, ActionScript does allow for optional and rest parameters. Optional parameters allow you to define default values for parameters; this means the method does not require that a value be explicitly passed to the method when it is called.

To define a parameter as optional you need only to add an assignment operator and a default value when declaring the method. The following example makes b optional by giving it a default value of two:

function test(a:String, b:String = "two"):void {
  trace("Your message is " + a + " and " + b);
}

Note

The default value for a parameter must be defined as a literal value at authoring time.

Now that test() is defined with an optional parameter, you can call it with one or two parameters. If you specify just one parameter, the default value is used for the second parameter. If you specify two parameters, the value you specify for the second overrides the default value.

test("one");  // Displays: Your message is one and two
test("three", "four");  // Displays: Your message is three and four

Rest parameters let you pass zero or more additional parameters of unknown types to a function. You declare a rest parameter using a parameter name preceded immediately by three dots. Within the method, you can access the rest parameter values as an array. The following code rewrites test() so that it always requires at least one parameter, but it also allows for zero or more additional parameters. By convention, the rest parameter is called rest (though you may use arbitrary names for the parameter).

function test(a:String, ...rest):void {
  var message:String = "Your message is " + a;
  var i:uint;
  for(i = 0; i < rest.length; i++) {
    message += " " + rest[i];
  }
  trace(message);
}

If you want to return a value from a method, you need to do two things: specify the correct return type, and add a return statement. When you specify a return type, you’ll get both compile-time and runtime checking. A function set to return a String value must return a string, not a number, date, array, or any other type. A return statement immediately exits the function and returns the specified value to the expression or statement from which the function was called. The following rewrite of test() returns a string:

function test(a:String, ...rest):String {
  var message:String = "Your message is " + a;
  var i:uint;
  for(i = 0; i < rest.length; i++) {
    message += " " + rest[i];
  }
  return message;
}

Methods use the same public, private, protected, internal, and static modifiers as properties. If you omit the modifiers (as in the preceding examples), Flex assumes the methods are internal. The following declares two methods, one public and one both public and static:

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
    static private var _instance:Example;
    static public const TEST:String = "test constant";
    public function traceMessage(message:String):void {
       trace("Your message is " + message);
    }
    static public function getInstance():Example {
       if(_instance == null) {
         _instance = new Example();
       }
       return _instance;
    }
  }
}

Note

Unlike properties, it's common and acceptable to declare public methods. However, it's considered best practice that methods are carefully designed, especially if they're public. A public method can be called at any time, and it's important that they allow access in only very controlled ways.

Classes can and should have a special type of method called a constructor. A constructor is called when an instance of the class is created. An example is when you explicitly call a constructor as part of a new statement. The constructor method has these rules:

  • The method name must be the same as that of the class.

  • The method must be declared as public.

  • The method must not declare a return type or return a value.

The following constructor assigns a new value to the _loader property:

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
    static private var _instance:Example;
    static public const TEST:String = "test constant";
    public function Example() {
       _loader = new URLLoader();
    }
    public function traceMessage(message:String):void {
      trace("Your message is " + message);
    }
    static public function getInstance():Example {
      if(_instance == null) {
        _instance = new Example();
      }
      return _instance;
    }
  }
}

There are two additional special method types, called implicit getter and setter methods. These are declared as methods, but they are accessible as though they were public properties. The method declarations are identical to normal method declarations, except for the following:

  • Getter methods use the get keyword.

  • Setter methods use the set keyword.

  • Getter methods must not expect any parameters and must return a value.

  • Setter methods must expect exactly one parameter and must be declared with a void return type.

The following example declares a getter and a setter method, each called sampleProperty. In this example, a new private property is declared using the getter and setter methods as accessors. This is not a requirement for getter and setter methods, but it is a common use case.

package com.example {
  import flash.net.URLLoader;
  import flash.net.URLRequest;
  public class Example {
    private var _loader:URLLoader;
    static private var _instance:Example;
    private var _sampleProperty:String;
    public function get sampleProperty():String {
      return _sampleProperty;
    }
    public function set sampleProperty(value:String):void {
      _sampleProperty = value;
    }
    static public const TEST:String = "test constant";
    public function Example() {
      _loader = new URLLoader();
    }
    public function traceMessage(message:String):void {
      trace("Your message is " + message);
    }
    static public function getInstance():Example {
      if(_instance == null) {
        _instance = new Example();
      }
      return _instance;
    }
  }
}

You can call the getter method by using the method name as a property in a context that attempts to read the value. You can call the setter method by using the method name as a property in a context that attempts to write a value. The following example creates an instance of the Example class, then writes and reads a value to and from the instance using the getter and setter methods:

var example:Example = new Example();
example.sampleProperty = "A";   // Call the setter, passing it A as a parameter
trace(example.sampleProperty);  // Call the getter

Expressions

An expression is any ActionScript that can be evaluated. At its simplest, an expression might consist of just one literal value or one variable. More complex expressions combine several values and/or variables using operators. There are many types of operators in ActionScript, ranging from mathematical operators to Boolean operators to bitwise operators. Most operators operate on two operands. For example, the following uses variables as operands in conjunction with a multiplication operator:

unitValue * quantity

Generally, expressions aren't used in isolation. The preceding code multiplies the values from two variables, but it doesn't do anything with that product. That value would typically be used in an assignment statement or as part of a larger expression. Boolean expressions are often used in if and for statements, which we’ll see next.

Statements

Statements are the building blocks of an application. They define the actions and program flow. Statements tell the application to do something. They can consist of variable declarations, assignments, function calls, loops, and conditionals. You’ve already seen examples of variable declaration statements, as in the following:

var total:Number;

An assignment statement uses the equals sign (=) to apply the value on the right side to the variable on the left. For example, the following code assigns the product of unitValue and quantity to a variable called total:

total = unitValue * quantity;

A statement can also be a call to a function. The following example calls a trace() function, which is a built-in Flash Player function that writes to the console when running a debug version of an application in the debug player:

trace("This is a simple statement.");

So far, you’ll notice that each statement ends with a semicolon. All statements of these types should end with semicolons in ActionScript. These types of statements comprise the majority of ActionScript statements. However, there are some statements that do not end in semicolons. Those statements are looping and conditional statements, including while, for, and if statements.

Looping statements, like while and for, let you loop the execution of a group of statements as long as a condition is met. Here's an example of a while statement in ActionScript. This statement increments total as long as total is less than maxTotal:

while(total < maxTotal) {
  total += 5;
}

You can use for statements as a compact way to write common loops. The for statement syntax is similar to that of the while statement, except that in place of the one conditional expression, a for statement uses three expressions: initialization, condition, and update. The following for statement calls trace() five times:

for(var i:int = 0; i < 5; i++) {
  trace(i);
}

Conditional statements use Boolean expressions to make the execution of some statement or statements conditional. The following example adds five to total if total is less than maxTotal:

if(total < maxTotal) {
  total += 5;
}

You can use if statements on their own, as in the preceding example. You can also use if statements in conjunction with else clauses. You can use these clauses only as part of an if statement. If the if statement conditional expression evaluates to false, else clauses that follow are run until one of the conditions evaluates to true. It is possible to nest conditionals, and by convention the nested if statement starts on the same line as the else clause within which it is nested, creating what are often thought of as else if clauses (though they are technically else clauses with nested if statements). The following example adds five to total if total is less than maxTotal; otherwise, the code subtracts five:

if(total < maxTotal) {
  total += 5;
}
else {
  total −= 5;
}

The following example interjects an else if clause that tests whether the total is 20 more than maxTotal. If it is 20 more, it subtracts 10; otherwise, it goes to the else clause.

if(total < maxTotal) {
  total += 5;
}
else if(total > maxTotal + 20) {
  total −= 10;
}
else {
  total −= 5;
}

Arrays

Arrays are sets of data organized by integer indexes or keys. In ActionScript, arrays are instances of the Array class. New arrays are defined using an Array constructor as part of a new statement (which we’ll talk about in the next section), or using literal notation. The literal notation uses square brackets to create an array. The following creates a new empty array and assigns it to a variable:

var books:Array = [];

You can also populate an array by adding a comma-delimited list of values between the square brackets:

var books:Array = ["Programming Flex 3", "ActionScript 3.0 Cookbook"];

You can access specific elements of the array using array access notation. The following example retrieves the first element from the array (ActionScript arrays are 0-indexed) and displays it in the console (again, if you are debugging the application):

trace(book[0]);

You can also assign values to elements using array access notation, as follows:

book[2] = "Web Services Essentials";

Arrays are objects in ActionScript, and they have methods and properties like most objects. It’s beyond the scope of this book to delve into the Array API in depth. However, of the Array API, the length property and push() method are the most commonly used. The length property returns the number of elements in the array, and it is commonly used with a for statement to loop through all the elements of an array. The push() method allows you to append elements to an array.

ActionScript arrays are not strongly typed nor are they of fixed length. That means you can store any sort of data in an array, even mixed types. You could store numbers, strings, dates, custom types, and even other arrays in an array. Furthermore, because arrays are not of a fixed length, you can add items without concern for the allocated size of the array.

ActionScript has two ways of simulating hashmaps. The first of these is the Object type, which is the most basic of all object types. Unlike the majority of ActionScript classes, the Object class is dynamic, which means you can add arbitrary properties to Object instances. Although it is generally better to write data model classes than to store data in Object instances using arbitrary properties, there are cases when it is useful to use an Object instance as a hashmap/associative array.

The following example creates an Object instance and assigns several keys and values:

var authorsByBook:Object = new Object();
authorsByBook["Programming Flex 3"] = "Chafic Kazoun,Joey Lott";
authorsByBook["ActionScript 3.0 Cookbook"] = "Joey Lott,Keith Peters,Darron Schall";

ActionScript also has the flash.utils.Dictionary class, which can be used in a similar fashion to Object. However, the keys for Dictionary are evaluated using strict equality for nonprimitive types, and objects used as keys must point to the same identity. In contrast, when using an Object as an associative array, the keys are tested using standard equality for nonprimitives, and objects used as keys can point to different identities as long as the toString() methods return the same value. Consider the following example. In this code, we create four keys to use: two are objects with toString() methods that return the same value, one is a primitive string, and one is a primitive integer. We then create two associative arrays—one an Object and one a Dictionary—and we populate them each with one element using the primitive string 1 as the key. Then we trace the values for each of the four keys for each of the associative arrays.

var key1:Object = new Object();
key1.toString = function():String {
    return "1";
};
var key2:Object = new Object();
key2.toString = function():String {
    return "1";
};
var key3:String = "1";
var key4:int = 1;

var object:Object = new Object();
object["1"] = "a";

var dictionary:Dictionary = new Dictionary();
dictionary["1"] = "a";

trace(object[key1]); // a
trace(object[key2]); // a
trace(object[key3]); // a
trace(object[key4]); // a

trace(dictionary[key1]); // undefined
trace(dictionary[key2]); // undefined
trace(dictionary[key3]); // a
trace(dictionary[key4]); // a

Because the Object always uses standard equality and evaluates the toString() method of objects used as keys, all four of the keys will work for access to the one element stored in the Object. The case is different for the Dictionary object. Because objects used as keys in this case must point to the same identity, neither of the object keys can be used to access the value. Because strict equality doesn’t apply to primitive types used as keys, either a string of 1 or an integer of 1 will work as a key to access the value.

Objects

Objects are composites of state and functionality that you can use as elements within ActionScript code. There are potentially an infinite range of object types, including those from the built-in Flash Player types to Flex framework types to custom types.

An object is an instance of a class, which is a blueprint of sorts. Although there are other mechanisms for creating objects, the most common is to use a new statement with a constructor. The constructor for a class is a special function that shares the same name as the class. For example, the constructor for the Array class is called Array. Like any other functions, a constructor may or may not expect parameters. The only way to know whether a particular constructor expects parameters is to consult the API documentation. However, unlike most functions, a constructor must be used as part of a new statement, and it always creates a new instance of the class. The following example creates a new array using a new statement:

var books:Array = new Array();

Objects may have properties and methods depending on the type. Properties are essentially variables associated with an object, and methods are essentially functions associated with an object. You can reference properties and methods of an object in ActionScript using dot syntax. Dot syntax uses a dot between the name of the object and the property of the method. The following example uses dot syntax to call the push() method of the array object (the push() method appends the value as an array element):

books.push("Programming Flex 3");

The next example uses dot syntax to reference the length property of the array object:

trace(books.length);

Get Programming Flex 3 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.