ActionScript 3.0 Fundamentals - Foundation ActionScript 3, Second Edition (2014)

Foundation ActionScript 3, Second Edition (2014)

Chapter 2. ActionScript 3.0 Fundamentals

This chapter covers how to do the following:

· Store information in your projects using variables

· Choose the right data type for the information you need to store

· Create constants to store information that never changes

· Perform arithmetic and make decisions

· Perform a set of actions repeatedly by using loops

· Separate common parts of code into functions

· Comment your code so that you and others know what it does

In this chapter, you will learn about the basic fundamental building blocks of the ActionScript 3.0 language.

I’ll warn you in advance that this chapter is probably the most challenging chapter in the whole book for new programmers because there is a wealth of information covered, but it is also the single most important chapter if you’re new to the ActionScript 3.0 language. The knowledge you pick up in this chapter will be used throughout the rest of the book and in every single project you work on as a full-fledged ActionScript developer. I’ll try my best to make the process as fun and as light-hearted as possible, but you’ll need to put in a bit of effort, too.

Image Note If you’ve already dabbled with a bit of basic ActionScript 3.0, you might just want to skim this chapter or skip it completely. It will always be here if you get stuck later on and need a little refresher.

It might help to imagine that reading this chapter is like learning to walk. It will be hard work and even confusing at times, and you’ll fall down occasionally, but once you’ve mastered the basics of walking you can go anywhere you want. After you’re mobile, you can then turn your attention to all the other fun stuff—such as examining the contents of the cookie jar that was hitherto out of reach—and the hard slog will have been worthwhile.

All right, that’s enough of the metaphors—on with the show!

Statements and Expressions

Everything in ActionScript (and really any programming language) can be broken down into statements. Just as a book is a series of sentences strung together, so too is a program a series of ­statements. Here is one statement in ActionScript:

var age:Number = 30;

Here is another:

trace(age);

And one more:

if ((year - age) < 2000) {
trace("You were born last millenium.");
}

All three of these statements look different, but they have a couple of things in common. First, and perhaps most obvious visually, is that they all terminate with a semicolon. This is known in ActionScript as a statement terminator, which lets the ActionScript compiler know that the statement is complete, just like a period at the end of a sentence. Although this is not necessarily required, it is good form and best practice, and from here on out I’ll pretend that it is a requirement as I present the examples. No one likes a sentence that doesn’t end with the proper punctuation!

The second common factor with the preceding statements is that they all form a complete command, or even a number of commands, like an instruction for ActionScript. The first line creates a number variable and gives it a value. The second line of code sends the value to be displayed in the Output panel in the Flash IDE or to the Console in Flash Builder. The third line of code traces a series of characters to the Output panel or the Console, but only if a certain condition is met. Don’t worry about understanding any of this code now; just know that a statement is a complete instruction in ActionScript and you’ll be all set.

An expression, on the other hand, is not a complete instruction; it’s a value (or values) that can be evaluated to determine a single resultant value. For instance, two simple expressions follow:

true
1

Expressions can be as simple or as complex as you need them to be, but in the end, Flash will determine their single value upon evaluation. As a final example, consider the following lines:

var price1:Number = 55;
var price2:Number = 10;
trace(price1 > price2);

The result is true.

In this case, the expression is actually line three of the code that evaluates price1 and price2. Using the trace statement, you can see that the expression evaluates to true because price1 is a greater amount than price2.

Introducing Variables

The next step on your journey is to take a look at the humble variable. If you’ve ever written any kind of program before, you probably already know that a variable is a named container in which you can store information to be used at a later stage in the program. The type of information you can store in an individual variable is governed by the variable’s assigned data type. If you didn’t know that before, well, you do now.

Before you can store any information in a variable, you first have to create or declare it. Let’s jump right in at the deep end and take a look at a variable declaration:

var bookTitle:String;

OK, that’s not too scary, but what does it all mean? You start with the var keyword, which tells ActionScript that you’re about to create a new variable. Next is the variable name or identifier, bookTitle, which is a unique name for this variable. You can use this identifier in future code to read or change the value of the variable. Note that ActionScript is a case-sensitive language, so booktitle and bookTitle are two completely different variables. If the name looks altogether odd to you, squished together like that into a single word with odd capitalization, know that there are many ways you can name a variable as well as a few limitations and requirements. A section is coming up that dives more fully into naming conventions, so jump ahead if you need to or just go with it for the next page or so, and all your questions will be answered.

Finally, you have the data type of the variable, String, which is separated from the identifier by a colon character. When you specify a data type, you’re telling Flash what kind of information can be stored in this variable. In this case, the variable is designed to hold String data, which is a character or sequence of characters such as a person’s name, a stanza from a poem, or even the entire text of War and Peace if that’s your bag. I’ll talk more about data types in a few pages’ time.

Assigning a Value to a Variable

Now that you have a variable, you can assign it a value by writing the variable name, followed by a single equals sign, which is known as the assignment operator, and then the value:

var bookTitle:String;
bookTitle = "Foundation ActionScript 3.0";

This tells the Flash Player to take the string "Foundation ActionScript 3.0" and store it in the ­bookTitle variable you created earlier. Simple.

Notice that the string value is enclosed in double quotes? This is how you can tell that a particular sequence of characters is a string literal, and not a bunch of program statements that it should try to make sense of and execute. You can actually use either single or double quotes; the only rule is that the closing quote must be the same as the opening quote.

A little trick you can use to cut down the number of lines of code in your ActionScript documents is to assign a value to a variable at the same time as when you create it. Using this technique you can cut the previous example down to just a single line of code:

var bookTitle:String = "Foundation ActionScript 3.0";

Of course, this is possible only if the value is known at the time of the variable declaration. Not only does this require less typing than the previous example—the value of which is directly proportional to the amount of code you write—but it’s also easier to understand. You know what the value of your variable is as soon as it is created because you explicitly told Flash what you want that value to be.

Retrieving the Value of a Variable

After you create a variable and give it a value, you want to be able to make use of that value at some point later in your code. Let’s face it—if you couldn’t use the value of a variable once it’s been set, variables would be about as useful as a chocolate fireguard (and nowhere near as tasty).

Thankfully, you can get the value of a variable just by using its name in a statement. How that value is used depends on the nature of the statement in which it appears. This might seem a bit confusing, so let’s look at an example:

var bookTitle:String = "Foundation ActionScript 3.0";
trace(bookTitle);

Here you added one statement to the earlier example. You can see the bookTitle variable there, but I can almost hear you asking, “What’s the trace stuff all about?” trace is the name of a function that is part of the Flash framework, and its sole purpose is to display information in the Output panel in the Flash IDE or the Console window in Flash Builder. (From here on out, I’ll just refer to the Output panel for a trace—readers who are testing in Flash Builder, please assume that this refers to the Console in that application as well). I don’t want to dwell on functions here (they’re covered in more detail later in the chapter), except to say that they are reusable pieces of code that can be invoked using the name of the function followed by parentheses (or rounded brackets for those of you who didn’t swallow a dictionary), passing the function any information it needs to do its thing within the parentheses.

To test this small fragment, the easiest thing to do is to put it directly in your timeline. However, because Flex users don’t have a timeline, let’s create a couple of files that use a Document class so that both Flash and Flex users can try out the code.

Image Note If you are using Flash Builder, you can follow along with these steps, except instead of creating a FLA file and compiling through Flash you can create a new ActionScript project in Flash Builder and use the document class code that follows as the default application class. If you’re uncertain about how to create an ActionScript project in Flash Builder and test your applications, please consult the application’s documentation. I’ll assume a similar proficiency for Flex users as for Flash users and concentrate not on the applications, but on the ActionScript code.

1. If you haven’t created a project directory for Chapter 2, you should do so now. You can place this project directory in the same place where you stored the Chapter 1 project directory.

2. Create a new ActionScript file and save it into the new Chapter 2 project directory as ActionScriptTest.as. Enter the following code:

package
{

import flash.display.MovieClip;

public class ActionScriptTest extends MovieClip
{

public function ActionScriptTest()
{
init();
}

private function init():void
{
// chapter code will go here
}

} // end class

} // end package

For the rest of this chapter, you should be able to reuse this same file, just replacing the comments within the init() method. Don’t yet know what comments or the init() method are? No worries (it’s just the beginning of the book). That means replacing the following line with the code presented in each section:

// chapter code will go here

3. For this first example, replace the comment line with the following bold code. Just this once, I present the entirety of the code, but from here on out, you should know the section of code to replace in order to run these tests:

package
{

import flash.display.MovieClip;

public class ActionScriptTest extend MovieClip
{

public function ActionScriptTest()
{
init();
}

private function init():void
{
var bookTitle:String = "Foundation ActionScript 3.0";
trace(bookTitle);

}

} // end class

} // end package

4. Now create a new Flash document and save it as actionScriptTest.fla into the same directory as the ActionScript file. In the Property inspector for the document, type ActionScriptTest in the Document class field, as shown in Figure 2-1.

image

Figure 2-1. Entering the document class for the test file

5. If you test your movie now, you should see the Output panel pop up with the name of this book, as shown in Figure 2-2.

image

Figure 2-2. Output results from the ActionScriptTest class file

Well done! You now can create a variable, set its value, and retrieve it again. Using variables is actually a major part of programming, so although it might seem fairly insignificant, it will be something you use over and over.

Naming Your Variables

Before you set off to create variables with careless abandon, I would be failing in my duty as your guide if I didn’t talk to you about how to name your variables. There are three things you need to keep in mind when dreaming up names for the variables in your applications—one is required, and the other two are recommendations born out of decades of experience from the entire development community.

The first thing to keep in mind is that ActionScript needs to understand what you’ve entered as a valid variable name. There are a few rules you should follow when constructing your variable names if you don’t want Flash to throw an error and refuse to publish your movie.

A variable name must

· Consist only of letters, digits, the underscore character, and the dollar symbol

· Not start with a number

· Not be a reserved word

· Be unique

A reserved word is a name that has special meaning in the ActionScript 3.0 language, such as var or String. You can find a complete list of reserved words in Adobe’s ActionScript documentation.

Make sure that your variable names bear some relation to the information that you intend to store in them. If you’re creating a variable to store the name of your favorite computer game, call it ­favoriteComputerGame, not thingamabob. You’ll be grateful you did this when you update your code in four months’ time and don’t have to spend an hour trying to figure out what purpose a variable named doohickey might serve. Trust me; I’ve been there.

Finally, your variable names should be consistent. ActionScript is a case-sensitive language, so ­currentbalance, currentBalance, and CURRENTBALANCE refer to three different variables. So you should choose a naming convention for your variable names and stick to it throughout the project (if not across projects).

Although you’re free to invent your own, there are many existing naming conventions, the most common of which (at least in the ActionScript world) is called camel case.

In camel case notation, the second letter of each word in a variable name is capitalized. When several words are joined together to make one variable name (and if you squint real hard) you see a camel-hump-like effect created by the capital letters:

myFavoriteColor

I’ll be using this variant camel case notation for variable names throughout this book because it is the most common form of notation for ActionScript developers, and Flash and Flex use this notation for their supported ActionScript classes, but feel free to pick your own style if you prefer something else. It doesn’t matter which notation you use as long as it is consistent throughout your code.

If you are working on a large project across many developers, it is always a good idea to agree on a naming convention before you start your project so you’re not hindered by guessing what the variable is referencing or whether it is a property.

Fully capitalized words, such as EGGS or BACON, are normally used for declaring constants to show that they are different from a normal variable. Constants will be covered in more detail a bit later in the chapter.

Image Note Many companies have an in-house coding standards document with a section on variable naming conventions that all developers should follow. This makes it easier for multiple developers to work on the same project without having to worry about which naming convention the other developers are using. If you’re writing code within a company, see if it already has a designated naming convention.

Understanding Data Types

ActionScript 3.0 has a small number of basic data types—known as primitive data types—that you can choose from to store different types of information in your variables. All other data types in ActionScript 3.0 are made up from these primitive data types, so I’ll spend some time discussing what they are and how they are used.

Image Note In addition to the more complex data types (which you’ll learn about as you work your way through the rest of this book), you can create your own data types from these primitive building blocks. If that sounds like fun to you, you’re in luck because that’s one of the things you’ll be looking at in the next chapter.

The primitive data types are listed in Table 2-1, along with a description of information they are designed to represent.

Table 2-1. ActionScript 3.0 primitive data types

Data type

Represents

String

A single character or sequence of characters

Boolean

true or false values

int

Positive and negative whole numbers

uint

Positive whole numbers

Number

Positive and negative whole and real (fractional) numbers

*

Unassigned data type

Image Note If you’re wondering why int and uint are all lowercase, and the rest start with an uppercase letter, you’ll have to spend some quality time reading the ECMAScript standard, which ActionScript complies with. int and uint are actually low-level numeric types that are subtypes of Integer (which does not exist in ActionScript). The lowercase denotes this and also follows syntax shared by languages such as Java, C++, and C#. Inconsistencies like this within the language seem designed to make the jobs harder, but thankfully there are so few primitive data types that it’s relatively easy to remember which ones start with a lowercase letter. And with code hinting and code completion there to help you out, most of the time you don’t have to type them out in full, anyway!

If you try to store a different type of information in a String variable, such as a person’s age, you would get an error when you try to publish your Flash movie. This is known as a compile-time error, which is the compiler’s handy way of telling you something needs to be fixed in the code

You already used the String data type, so I won’t go over that one again, but the others are quite interesting, so you’ll spend some time looking at them in more detail.

Boolean Data Type

The Boolean data type is designed to represent values of either true or false. If you were to create an ActionScript program to simulate a room, whether the light in that room was on or off could probably be stored as a Boolean value (let’s not dwell on dimmer switches for the moment).

var lightsOn:Boolean = true;

There isn’t much more to say about Boolean variables, except that they are commonly used to make decisions in your code based on one of two states, as you’ll discover later in the chapter.

Numeric Data Types

The ActionScript 3.0 language has three numeric data types: int, uint, and Number. ActionScript 2.0 had only the Number data type in which to store numerical data, something that was both a blessing and a curse. It was a blessing because you didn’t have to worry about which numerical data type you should use, and a curse because its flexibility came at a cost: it used twice as much memory as necessary if all you wanted to store were whole numbers. Whether that was a real issue depended on how many variables you had in your code, but it always felt a little wasteful to me.

To counter this problem, ActionScript 3.0 introduced the int (short for integer) and uint (short for unsigned integer) data types, allowing you to create variables to store whole numbers without wasting memory. If you’re creating a program to track how much money is in your bank account, you’ll still have to use a Number variable to keep track of your balance because the money will require two decimal places, but you might use a uint to store the number of transactions because they will be whole numbers. Similarly, if you were creating a darts game, you would use int instead of Number variables to keep track of the scores.

Unfortunately, choosing the right data type isn’t just about whether you want to store positive or negative numbers, or even whole or real numbers; it’s also about how big a number you’re trying to store.

In Table 2-2, you can see the minimum and maximum values that can be stored in the new integer data types.

Table 2-2. Minimum and maximum values for the integer data types

Data type

Minimum value

Maximum value

int

–2,147,483,648

2,147,483,647

uint

0

4,294,967,295

As you can see (well, if you do a little math in your head), both can store the same amount of numbers, but although uint, being unsigned, stores only positive integers, int stores both positive and negative integers. The result is that the maximum number a uint can store is double that of an int, but it can’t store negative numbers. So you have to choose wisely and be sure which values you have to store before deciding on the data type of a given variable.

Image Note What happens if you try to store a negative number in a variable of type uint or a real number in an int? Get down with your inner geek and try it out—half the fun of learning something new is experimenting.

What happens if you want to store a number higher than 4,294,967,295 or a negative number less than –2,147,483,648? You have to switch to using a Number variable instead. I didn’t list the values for Number because they’re so gargantuan that I’d wear out the keyboard typing all the digits. If you really want to know the minimum and maximum values (and if you dig scientific notation), enter the following lines of code into a new movie and see what you get in the Output panel:

trace("Minimum: " + Number.MIN_VALUE);
trace("Maximum: " + Number.MAX_VALUE);

If you give this a go, you’ll see that Number can handle some seriously big numbers. If you’re feeling lazy, imagine the number 179 with 305 zeroes after it (in both positive and negative directions), and you won’t be far off.

Having to store such a huge range of numbers, it’s inevitable that the Number data type has at least one quirk, and this one’s a doozy: 0.1 plus 0.2 does not equal 0.3—at least not exactly. Seemingly flying in the face of basic mathematics, 0.1 plus 0.2 will give 0.300000000000004. The reason for this inaccuracy has to do with the way the information is represented in the computer’s memory and has caused many developers to spend all night searching for bugs in their code. Don’t think ill of ActionScript, though; this problem plagues most modern programming languages including JavaScript, PHP, Python, and Ruby.

Using Constants

Constants are similar to variables in that they have an identifier, a type, and a value, but their value cannot be changed once they have been set. Constants are declared using the const keyword:

const DAYS_PER_WEEK:uint = 7;

As illustrated in the preceding line, it is an established convention that the names of constants are specified in all uppercase letters, and words are separated with an underscore. This makes it easy to distinguish between constants and variables at a glance wherever they are used.

Image Note It is also a common convention to have constants be static properties of a class, but because I haven’t covered classes or properties yet, I’ll save further discussion until a later example.

Deciding what should be a constant and what should be a variable can sometimes be tricky, but any value that is not to be changed at runtime and will be consistent throughout the life cycle of the application is usually a good candidate for a constant. I often separate this out even further, keeping values that will always be the same each time a program is run as constants, while making into variables those values that can change each time a program is run (even if they are consistent during a single session). For instance, because DAYS_PER_WEEK in a calendar will always be seven (even if you display less), it would make a good constant. However, currentYear (even though it would be consistent through a single session—unless the program was run on New Year’s Eve—but let’s not quibble) would be better served as a variable value.

One common use for constants is to replace magic values in your code to aid readability, particularly if they are used in more than one place in your code. Magic values are hard-coded values within larger statements in which the purpose of the value or how it was derived may not be immediately apparent. For example, take a look at the following code:

var totalAmount:Number = amount + (amount * 0.175);

This example performs some simple arithmetic (which I’ll cover in a moment) to calculate the total cost for a hypothetical shopping basket full of goodies. You might be able to deduce that the number 0.175 represents the tax rate as a decimal fraction, but you’d know that only by looking at the whole statement. It’s much better to replace this magic number with a constant:

const TAX_RATE:Number = 0.175;
var totalAmount:Number = amount + (amount * TAX_RATE);

Now that’s much more readable. It also means that if you ever need to change the tax rate, you’d have to change only the line in which the tax rate constant is defined instead of having to search for every occurrence of the magic number.

Performing Operations

No, you haven’t accidentally replaced your ActionScript book with a medical text. Operations in programming are expressions evaluated using a set of common operators. You will be familiar with many of these operators from the world of mathematics, and their functionality remains mostly consistent with what you learned in your early schooling. Let’s take a look at the common operators used for arithmetic before I discuss some of the unique operator usage with programming.

Arithmetic Operators

You’ve already seen a few examples of how to do basic arithmetic in the previous section. In ActionScript (or in any programming language, in fact), the symbols used for arithmetic are referred to as arithmetic operators. Table 2-3 describes the complete set of arithmetic operators in ActionScript 3.0.

Table 2-3. Basic arithmetic operators

Operator

Description

+

Addition

-

Subtraction

* (asterisk)

Multiplication

/

Division

%

Modulo

The function of most of these arithmetic operators should be familiar to you; even if the symbols are slightly different, they’re essentially the same ones you learned to use at school when you were eight years old. Each of these operators requires two operands arranged in the following way:

[operand 1] [operator] [operand 2]

Examples of each of the operators using the same operand values follow:

trace(10 + 4);
trace(10 - 4);
trace(10 * 4);
trace(10 / 4);
trace(10 % 4);

Test this code in a new Flash movie, and it will (rather unsurprisingly) give you the following in the Output panel:

14
6
40
2.5
2

Image Note The one that may seem a little quirky (and the one I hadn’t heard of before I started programming) is the modulo operator. This operator gives you the remainder after the second operand has been divided into the first operand as many times as possible. In the preceding example, 4 goes into 10 twice with 2 left over, so the result of the expression is 2.

Because each of these operators requires two operands, they are all known as binary operators. There are also unary operators (one operand) and even a ternary operator (three operands). I’ll discuss unary operators shortly, but will leave the more complex ternary operator until later in this book when you are more familiar with the basics.

You can string multiple arithmetic operators together to form complex expressions:

trace(10 / 2 * 5 + 4 % 3);

Which part of the overall expression is evaluated first? The value in the Output panel after running the previous line of code is 26, but I bet that (like me) you’d have to work hard to figure out why just by looking at the expression itself. If you want to know what you can do about it, read on.

Specifying Precedence

The order in which the arithmetic operators are evaluated is also the same as you probably learned in school. In the United Kingdom, children learn the BODMAS acronym, which gives the order in which arithmetic operators should be evaluated: brackets, orders, division/multiplication, addition/subtraction. In the United States, this is known as PEMDAS, which uses different terminology for the same thing: parentheses, exponents, multiplication/division, addition/subtraction.

Why is this important? ActionScript 3.0 follows the same basic rules when evaluating arithmetic expressions. This means that the following expression will actually evaluate to 15, not 10, because division is evaluated before addition:

trace(10 + 10 / 2);

Thankfully, in ActionScript (as in real-life arithmetic) you can use parentheses (or brackets) to explicitly specify the order in which the various arithmetic operators in the expression are evaluated:

trace((10 + 10) / 2);

In this case, it was necessary to use parentheses to get the desired result, but I advise always using parentheses in your expressions, even if they would work as intended without them. Doing so makes it much easier to see what’s going on without having to remember the proper evaluation order for the arithmetic operators.

Using your newfound knowledge of precedence and employing the goal of using parentheses to make precedence clear, you can rewrite the complex expression you met earlier to make it clearer:

trace(((10 / 2) * 5) + (4 % 3));

I don’t know about you, but I can see exactly what’s going on there now. Ten divided by 2 is 5, which when multiplied by 5 gives 25. Four modulo 3 is 1, which when added to the 25 gives 26. Hurrah!

String Operations

One of the arithmetic operators in the previous section is also used with strings (you might hear this referred to as the operator being overloaded, meaning that it has multiple functions based on its operands), so you might see the following in code:

var fullName:String = "John " + "Doe";

Here, the plus sign is used to join together, or concatenate, two strings to form a single string, which is then assigned to the fullName variable. This string functionality is unique to the plus operator—you cannot use the other arithmetic operators with strings, such as trying to subtract one string from another.

Unary Operations

As stated earlier, a unary operation involves a single operand, not the two operands used with arithmetic operators. The most common unary operators are listed in Table 2-4.

Table 2-4. Unary operators

Operator

Description

!

Logical negation

-

Negative

+

Positive

++

Increment

--

Decrement

The two operators you are probably familiar with are the positive and negative operators. The negative operator changes positive values to negative and negative values to positive, as demonstrated in the following example:

var number:int = 10;
trace(number);
number = -number;
trace(number);
number = -number;
trace(number);

It produces this result:

10
-10
10

The positive operator, which is equivalent to multiplying a number by a positive one, does not really have much effect in its operations and is more useful for making code more legible by specifying clearly that a number is positive.

Another unary operator that is often used is the logical negation operator (!). This operator works with Boolean values and, similar to how the negative operator works with numbers, causes true values to become false and false values to become true. When is this useful? Often, you might have Boolean variables or functions named based on positive assertions, such as isSignedIn or ­editAllowed(). It makes more sense logically when reading code to have these positive assertions as opposed to negative assertions (isNotSignedIn, for instance). However, if you need to check whether someone wasn’t signed in before performing some necessary action, the easiest way is to use the logical negation operator on the isSignedIn variable. You’ll learn more when I cover conditional statements later in this chapter, but the basic syntax follows:

if ( !isSignedIn) {
statements
}

This can be read as follows: “If the user is not signed in, run these statements.”

The other unary operators listed include the increment and the decrement operators. They are most useful in loops, so I’ll leave their discussion until that section is discussed.

Introducing Arrays

Variables and constants work well, but sometimes the information you need to store is better organized in an Array object. An Array is one of the more complex data types I mentioned earlier, and it is designed to store sequential information in a more convenient fashion than using a series of variables. An example might help to make this clear.

Suppose that you’re creating an address book application and you need to store the names of all your contacts. You could create several variables—contactName1, contactName2, contactName3, and so on—but you would need to know how many entries there will be in the address book in advance to create the correct number of variables. Instead of going through all that pain, you could use an Array to store all the contact names in a single variable, in which each individual contact is kept separate but accessible. So contactName might be an array, or list, of values, and you could then use special Array syntax to retrieve individual contacts from this list.

If you are still having some trouble understanding what an array is, it might help to imagine an array as a filing cabinet in which you can store only one item in each drawer. Imagine that each drawer in this filing cabinet holds the information about one of your contacts (you collect a lot of data on your contacts—you’re paranoid). So although you have multiple contacts, the data for all these contacts is stored in single filing cabinet. If you want to refer to the collection of contacts, you could point to the filing cabinet as a single entity and say, “That is my collection of contacts.” But if you need information on a single contact within that collection, you could refer to a single drawer and access that information (see Figure 2-3).

image

Figure 2-3. An array is like a filing cabinet that stores something in each drawer

There are several ways to create an Array object. The simplest is to use the Array constructor using the new operator:

var myArray:Array = new Array();

The new operator is something you will become familiar with very quickly because it is the way to create almost any type of ActionScript object. You simply place it before the name of the object you want to create an instance of, followed by parentheses (this is actually a class’s constructor, but I’ll get to that in the next chapter) and—voilà!—you get your object.

You can also pass some values within the parentheses (called parameters) to give special instructions to or populate your array. For instance, if you pass in a number, it tells the array that it will be of a certain length, meaning that it will contain a certain number of items in its list:

// an array with five "slots" ready to hold data
var myArray:Array = new Array(5);

If you pass in something other than a number or if you pass in more than one value, these will be the initial values stored in the array:

// an array holding a single string initially
var charArray:Array = new Array("one");

// an array holding five numbers
var numArray:Array = new Array(5, 23, 35, 52, 100);

The way you most often create an array, however, is by using an array literal, which is a comma-separated list of values enclosed in square brackets:

var myArray:Array = [value1, value2, value3, ... valueN];

Continuing the contacts collection example, creating an array to hold contact names might look like this:

var contactNames:Array = ["Rod", "Jane", "Freddy"];

If you want to find out the contents of an array, you can just pass it to the trace() function:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames);

This will give you a comma-separated list of all the values in the array:

Rod,Jane,Freddy

You can also tell how many values are in the array using the Array object’s length property. I’ll talk more about objects and their properties in the next chapter, so don’t worry if seems confusing. All you need to know is that objects can have properties, which are preassigned variables specific to the object, and you can access the properties of an object using dot notation. To get the property of an object, specify the name of the object, followed by a period, and then followed by name of the property.

If you work this into the example, you can find out how many elements are in the contactNames array:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames.length);

The values in an array are stored sequentially, by number, with the first value at index 0, the next at index 1, and so on. You can read the individual values from an array using subscript notation, which is a fancy way of saying you put the index of the desired value between square brackets after the variable name. Using subscript notation, you could change the previous example to output only the second contact name in the address book:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames[1]);

If you test the preceding code, you should see Jane in the Output panel. If you were expecting to see Rod, remember that the index of an Array object starts at zero—in geek parlance, Array objects are zero indexed.

Manipulating Arrays

One of the benefits of arrays over sequentially named variables is that an array can store a nearly unlimited number of values. Once you have created an array, you can update or add a value using subscript notation in the same way you would set a normal variable’s value.

For example, if you want to update Rod’s name to Rodney, you could do this:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
contactNames[0] = "Rodney";
trace(contactNames);

Running the preceding code would now produce the following in the Output panel:

Rodney,Jane,Freddy

Adding a value to the array is also easy to do. Actually, you have several ways to add a new value to an array: you can do so using subscript notation or you can use one of the Array object’s many insertion methods. One of the easiest to use is the push() method, which adds the value to the end of the array. For the contactNames example, the following two statements are identical:

contactNames[3] = "Bungle";
contactNames.push("Bungle");

Either of the preceding statements results in the string Bungle being added as the fourth element in the contactNames array:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames);
contactNames.push("Bungle");
trace(contactNames);

So that’s how you update existing values and add new ones to an array, but how do you remove them? Again, you have several choices, depending on your desired result. If you simply want to clear a value in an array, you can use the delete keyword:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames);
delete contactNames[1];
trace(contactNames);

If you trace the value of the contactNames variable after using the delete keyword on one of its elements, you’ll see the following in the Output panel:

Rod,Jane.Freddy
Rod,,Freddy

Pay very close attention to this output—notice that although Jane has been deleted, there is still a place reserved for her in the array, as indicated by the two commas between Rod and Freddy in the output. So delete clears a value but leaves its place in the array.

If you want to obliterate Jane completely (poor Jane—what did she ever do to you?), the easiest way is to use the splice() method of the Array object. This method removes a number of items from the specified position in the array and (optionally, although you won’t be using it in this case) inserts one or more values in their place.

If you replace the delete statement with a call to the splice() method instead, you can completely remove Jane from the contactNames array:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
trace(contactNames);
contactNames.splice(1,1);
trace(contactNames);

This can be read in English as follows: “Starting at index 1, remove one element from the ­contactNames array.” That’s exactly what it does.

Running the example now produces the following result in the Output panel:

Rod,Jane,Freddy
Rod,Freddy

There, Jane is completely gone. I don’t know what she did to fall out of favor with you, but it’s now as though you tore the page from your address book instead of just scribbling her details. Remind me not to get on your bad side.

That’s just about all you need to know about arrays for the moment. There are quite a few more methods for manipulation if you care to peruse the ActionScript documentation, but I’ll introduce them as needed for the examples. If you can’t get enough, the good news is that you’ll be revisiting them shortly when you look at looping a little later in the chapter. Loops and arrays go together like birds of a feather—or something like that, anyway.

Vectors vs Arrays

Vectors are typed arrays, which help to assure your collection is type safe. Using the Vector class is almost identical to arrays, as it includes the same methods as the Array class.

Vectors provide performance improvements over arrays through faster read and write access. Element access and iteration through the collection is faster. They enable runtime range checking (or fixed-length checking). In strict mode, the compiler can identify data type errors.

The main difference between vectors and arrays are how they are instantiated. For example, using the new operator to create a vector of strings:

var myVector:Vector.<String> = new Vector.<String>();

Like arrays, initial values may be passed either using the Vector.<T>() global function or new operator. The following two statements are equivalent:

var contactNames:Vector.<String> = Vector.<String>(["Rod", "Jane", "Freddy"]);
var contactNames:Vector.<String> = new <String>["Rod", "Jane", "Freddy"];

Also similar to arrays is the ability to specify the number of items the vector will store by passing a number to the constructor. By specifying the initial length, that number of elements will be created and populated with the default value appropriate to the base type (or null for reference types).

var myVector:Vector.<int> = new Vector.<int>(2);

Vector length can be fixed, meaning you cannot modify the total number of elements it can hold. Once a vector length is fixed, any operation that modifies length throws a RangeError at runtime. In memory, vectors are stored as a single unbroken block of data; so, preallocating their size increases performance instead of the vector growing and reallocating additional memory.

Length can be fixed when the vector is created by setting the length and fixed parameters to true in the contructor:

var myVector:Vector.<int> = new Vector.<int>(2, true);
myVector.push(1);
myVector.push(2);
myVector.push(3); // RangeError – the Vector can only hold two items

The above code will throw a RangeError:

RangeError: Error #1126: Cannot change the length of a fixed Vector.

Or, you can set length to be fixed during runtime:

var myVector:Vector.<int> = new Vector.<int>();
myVector.push(1, 2, 3, 4, 5);

myVector.fixed = true;
myVector.push(6); // RangeError – the Vector length is now fixed

Vectors may be defined using many data types for the variables they hold. They may hold primitive values such as String, Number, int, Boolean; or, complex values such as Object, Date, XML, or custom classes. Once declared, assigning an incompatible type throws a compiler error. For example, if a vector is declared with a type of int, adding any other data type that cannot be converted to int will throw an implicit coercion error:

var myVector:Vector.<int> = new Vector.<int>();
myVector[0] = "one";

The above code will throw an implicit coercion error because the Vector type is defined as int. Only integers may be added to the collection. Trying to add a string will result in the following error:

1067: Implicit coercion of a value of type String to an unrelated type int.

Multiple data type values can be added to a Vector if they can be implicitly converted, such as adding a class that derives from the destination class. For example, if you declare a Vector of type DisplayObject, any subclass that inherits DisplayObject as a base class can be added:

var myVector:Vector.<DisplayObject> = new Vector.<DisplayObject>();
myVector[0] = new MovieClip();
myVector[1] = new Sprite();
myVector[2] = new Shape();

In the above example, a MovieClip, Sprite, and Shape were added to the vector because they all extend DisplayObject.

Understanding Type Checking

As a dynamically typed language, ActionScript 3 has runtime type checking; however, in strict mode, type checking occurs at both compile time and runtime. Beyond performance improvements, understanding data types helps as applications grow in size and increase complexity. Code becomes more predictable, errors are discovered during compilation, and applications become more stable.

Image Note Data typing is the ability to give both the compiler and Flash Player information about the type of data stored in memory. By providing this information, the tools can check to ensure your code doesn’t perform illogical operations, such as trying to assign the word “help” to a date object. Further, based upon this type information, Flash Player can make more intelligent decisions leading to faster execution of your program.

Type checking can occur at either compiler time or runtime. Dynamically typed languages offer tremendous flexibility when you structure your code, but at the cost of allowing type errors to manifest at runtime. Statically typed languages report type errors at compile time, but at the cost of requiring type information be known at compile time.

Making Decisions

Up until this point, all the code you’ve written has been of a sequential nature: program statements that execute one after another until the end of the code is reached. In your ActionScript projects, there will be points at which you want to decide to do one thing or another based on some condition. For example, if a user has accidentally entered his age as 234 instead of something more sensible like 23, you’d want to show him a nice error message (or ask him what his secret to longevity is).

To allow for this kind of scenario, you need to be able to make decisions in the projects. Thankfully ActionScript provides a number of solutions to this problem: the decision-making, or conditional, statements.

Introducing the if Statement

The simplest conditional statement in ActionScript is the if statement. Similar to its namesake in the English language, you can use the if statement to qualify that a particular block of ActionScript is executed only if a given condition is true.

An if statement takes the following form:

if (condition) {
statements
}

If the condition (which is a Boolean expression) evaluates to true, the statements inside the following block will be executed. If not, they’ll be skipped. The code block is determined by the opening and closing curly braces, if there are multiple lines of code to be run within the conditional. Fancy an example?

trace("Before");
if (true) {
trace("Condition is true");
}
trace("After");

If you enter the preceding example and then run it, you’ll see the following in the Output panel:

Before
Condition is true
After

The condition portion of the if statement evaluated to true, so the trace() statement within was executed.

Image Note In practice, the condition of an if statement is more complex than the example shown previously. You’ll look at how to build more complex condition expressions later in the chapter.

Suppose that you now change the example so that the condition evaluates to false:

trace("Before");
if (false) {
trace("Condition is true");
}
trace("After");

You can see that the trace() statement within the if statement is skipped:

Before
After

You can spice things up a bit by adding an else block to the if statement. The else block tacks into the end of the closing brace of the if statement like this:

if (condition) {
statements
} else {
statements
}

The statements in the else block are executed only if the condition in the if statement is false. If you incorporate this into the previous example, you see a nice message in the Output panel either way:

trace("Before");
if (false) {
trace("Condition is true");
} else {
trace("Condition is false");
}
trace("After");

It produces the following output:

Before
Condition is false
After

I cheated slightly with the preceding examples by hard-coding either true or false. The real power of the if statement becomes apparent when you use a Boolean expression in the condition.

Forming Boolean Expressions

A Boolean expression is one that evaluates to either true or false. Indeed, the keywords true and false are themselves the simplest form of Boolean expressions. More complex Boolean expressions are formed using conditional or equality operators. (Table 2-5 contains a list of the most common.)

Similar to the arithmetic operators you saw earlier, these operators require an operand on either side:

[operand] [operator] [operand]

Each compares the left operand with the right operand to produce either a true or false answer:

10 > 4

The preceding line could be read as “10 is greater than 4.” A Boolean expression can be either true or false (in this case, it is true). The great thing is that Flash takes care of determining whether the expression is true or false. So an expression (20 < 10), which can be read “20 is less than 10,” is evaluated by Flash to be false. So in the following lines of code, the variable canBuy is set to true because Flash will determine that the price is less than the cash:

var cash:Number = 20;
var price:Number = 5;
var canBuy:Boolean = (price < cash);

The expression on the right of the last line (price < cash) is evaluated to be (5 < 20), which is further evaluated by Flash to be a true statement, so a value of true is assigned to the variable canBuy.

Let’s see an example of all the operators in action:

trace(10 == 4);
trace(10 != 4);
trace(10 < 4);
trace(10 > 4);
trace(10 <= 4);
trace(10 >= 4);

This will produce the following output (if you’re unsure about why a particular expression evaluates to true or false, try reading each expression aloud, replacing the operator with the description from Table 2-5):

false
true
false
true
false
true

One operator to definitely watch out for is the equality operator (==), which is used to check whether one value is equal to another. This should not be (but often is) confused with the assignment operator (=), which you have already seen in action when assigning values to variables. Where this really can bite you is within a line that you expect to be true or false by using the equality operator, but you instead assign a value, as in the following example:

var age:Number = 30;
if (age = 16) {
trace("You can drive a car (legally)!");
}
trace(age);

Although you might think that the contents within the if block would be skipped, and the age would be traced as 30, what actually happens is that the expression (age = 16) evaluates to (16) because 16 is first assigned to the age variable using the assignment operator. Then the resulting value of age is evaluated. Any nonzero number evaluates to true within a conditional, so the end result is that not only will age be assigned a new value but the contents of the if block will also be run. Bad news! (Fortunately, Flash gives you a warning when you do this.) The lesson is to always be aware of the difference between the equality operator and the assignment operator.

Booleans in Conditionals

I mentioned earlier that you might want to show a polite error message if users enter an impossible value for their age. In more concrete terms, you want to show an error message if the age entered is greater than 130. To do this, you can construct a Boolean expression to test values and then plug it into an if statement. Looking at the list of operators available, one of them fits your needs perfectly:

var age:uint = 159;
if (age > 130) {
trace("I think you made a mistake");
}

Running the preceding example, you should see that the expression evaluates to true, and the trace() statement is executed:

I think you made a mistake

You can also test that the expression evaluates to true by just tracing the following:

trace(age > 130)

The preceding traces true to the Output panel.

Now that you can see Boolean expressions working in conditional statements, you can add just a little more to your conditional repertoire, as it were. You already know that you can follow an if conditional with an else conditional. You can also nest if statements within any other code block, including other conditionals. For instance, see if you can follow the logic in the following example:

var language:String = "ActionScript";
if (language == "Java") {
trace("You need a Java book!");
} else {
if (language == "ActionScript") {
trace("You're in the right place!");
} else {
trace("I don't know what you're reading.");
}
}

Notice that another if else conditional is put within the else conditional. This can continue to be as nested as you need. In the preceding example, though, you can actually employ another conditional variant: the else if conditional. The following lines have the same result as the ones from the previous example:

var language:String = "ActionScript";
if (language == "Java") {
trace("You need a Java book!");
} else if (language == "ActionScript") {
trace("You're in the right place!");
} else {
trace("I don't know what you're reading.");
}

Even though the last two examples have the same result, it is important to note the difference. When you have an if else statement, at least one of conditional code blocks will be run because if the first if condition evaluates to false, the else block will run. However, with anelse if statement, a block will be run only if its conditional is met, which makes it possible that neither block could be run.

Sometimes the nesting of conditionals is necessary; sometimes a series of if else if statements will work; sometimes you need a combination of both—it all depends on what you need to accomplish with the conditions at that point in your code. There’s also a handy little structure called the switch statement that will also handle conditionals, but I’ll roll that out when you need it later in the book (I’m throwing enough at you as it is!).

Using Logical Operators

You can form more complex Boolean expressions by logically joining them together using Boolean operators, which are listed in Table 2-5.

Table 2-5. Boolean operators

Operator

Description

&&

AND: evaluates to true if both operands are true; otherwise evaluates to false.

||

OR: evaluates to true if either operand is true; otherwise evaluates to false.

Using these Boolean operators, you can join together two or more Boolean expressions to form a larger Boolean expression.

For example, let’s say that you want to go to the movies, but only if you have enough money, aren’t working, and have someone to go with. The conditions under which you would go to the movies could be written as a Boolean expression using English like this:

have enough money AND not working AND have company

This can be translated into ActionScript simply if you assume that you have Boolean variables defined for each part of the decision:

haveEnoughMoney && notWorking && haveCompany

You can then plug this expression into an if statement to see whether you can go to the movies:

var haveEnoughMoney:Boolean = true;
var notWorking:Boolean = true;
var haveCompany:Boolean = true;

if (haveEnoughMoney && notWorking && haveCompany) {
trace("Go to the movies");
} else {
trace("Go another time");
}

You can go to the movies only if all three parts of the Boolean expression evaluate to true. You can also revise the expression to say that you might consider going to the movies on your own, but only if the film is really good. In English, it would be the following:

have enough money AND not working AND either have company OR good movie

Translated to ActionScript, it looks like this:

haveEnoughMoney && notWorking && (haveCompany || goodMovie)

Working this into the example, you get this:

var haveEnoughMoney:Boolean = true;
var notWorking:Boolean = true;
var haveCompany:Boolean = false;
var goodMovie:Boolean = true;

if (haveEnoughMoney && notWorking && (haveCompany || goodMovie)) {
trace("Go to the movies");
} else {
trace("Go another time");
}

Now, you can go to the movies as long as both haveEnoughMoney and notWorking are true, and one (or both) of haveCompany or goodMovie is true.

Looping the Loop

So far, you had to manually type every single line of ActionScript that you want to be executed. If I were to ask you right now to write some code that would output the numbers 1 to 5 to the Output panel, you’d probably come up with something like this:

trace(1);
trace(2);
trace(3);
trace(4);
trace(5);

This would do the job as adequately as any other solution I could come up with, but it’s not the most efficient method. Imagine if, instead of 1 to 5, I had asked you to output 1 to 1000 to the Output panel. Assuming that you didn’t ignore me completely (and I wouldn’t blame you if you did), it would take you a while to write out all the individual trace() commands.

Thankfully, programming languages have the concept of loops to take away a lot of the tedium, and ActionScript is no different. Loops allow you to define a series of actions that will be performed again and again as long as a given condition is met.

ActionScript 3.0 has three basic looping statements: while, do...while and for, which you’ll look at individually in a moment. If you’re wondering why it’s necessary to have three different ways of repeatedly executing a block of statements, the answer is that they each work in a slightly different way. This means that sometimes a while loop is a better choice than a for loop, or a do...while loop is better than a while loop.

The while loop

The first stop on the whirlwind tour of looping constructs is the humble while loop. At first glance, the while loop looks remarkably similar to the if statement you met earlier:

while (condition) {
statements
}

The similarity is no accident. The while loop, like the if statement, has a condition that is tested to see whether it evaluates to true. If it does, the statements within the loop are executed repeatedly, with the condition being checked again at the start of each iteration of the loop. If the condition ever evaluates to false, the loop is exited, and execution continues with any statements that appear after the while loop.

To a while loop, the business of printing out a series of numbers is but a moment’s work:

var number:uint = 1;
while (number <= 1000) {
trace(number);
number++ ;
}

It’s important to note that the condition for the while loop is checked at the start of each iteration. Like the if statement, the condition portion of the while loop will be evaluated, and the statements within the while loop will be executed only if the condition evaluates to true. The statements within the while loop will be executed repeatedly until the condition evaluates to false.

Where the while loop differs from the if statement is that the statements within the while loop will be executed repeatedly while the condition evaluates to true, as opposed to only once.

Image Note If the condition always evaluates to true, the statements in the loop will run forever. However, like a petulant child, the Flash Player gets bored after 15 seconds stuck in one loop and asks users whether they want to halt the movie. This is a good thing because nothing will appear to be happening in the movie while the loop is infinitely running—no animation will be occurring, and no interaction will be allowed as Flash continues to evaluate the condition as true and runs the loop.

You should avoid this situation at all costs. If you need to have code run continually within your movie, there are better ways to handle this (for example, using a Timer or an onEnterFrame handler, both of which are discussed later in the book).

The condition of a while loop is evaluated at the start of each iteration. This means that if the condition initially evaluates to false, the statements within the loop will never be executed. In other words, the statements in a while loop will be executed zero or more times depending on the condition.

Let’s look once more at the while loop that was just presented, with a slight alteration, that will trace the numbers 1 to 1000 and break down exactly what is happening. Try out this code in a Flash movie:

var number:uint = 1;
while (number <= 1000) {
trace(number);
number++;
}

Here you first declare a uint variable named number and initialize it with the value of 1. You then set as a condition in the while loop that as long as number holds a value that is less than or equal to 1000, you should trace its current value to the Output panel and then add 1 to its value. At this point, the loop’s contents are complete, and the condition is tested once more. If number is still less than or equal to 1000, the loop’s contents are run yet again.

Running the preceding example gives you the following in the Output panel:

1
1
2
3
...
998
999
1000

There—the same result and much better than 1000 lines of code!

Image Note In the preceding example, the number variable is often referred to as the loop control variable because it alone controls when the loop stops. You don’t always have a single loop control variable—your conditions might be made up of complex Boolean expressions so that no one variable controls the loop.

No doubt you noticed the slight alteration of the last line of the while loop code block. What’s up with the odd ++ notation? This is known as the increment operator, which you might recall from the earlier discussion on unary operations. It simply adds 1 to the value of the variable specified and assigns this new value back to the variable. It is the equivalent of writing the following:

number = number + 1;

As you can see, though, it is the same result with less code and actually is easier to read (as you program more). There are two ways to use the increment operator, postfix and prefix, meaning that the operator can appear either before or after the variable. Each produces slightly different results, as the following should demonstrate:

var postfix:uint = 1;
trace(postfix++);
trace("postfix is now:", postfix);

var prefix:uint = 1;
trace(++prefix);
trace("prefix is now:", prefix);

The lines result in the following output:

1
postfix is now: 2
2
prefix is now: 2

The first trace of the first block uses a postfix increment, which increments the postfix variable after it has been evaluated in its current expression. This means that the value of 1 will be traced to the Output panel because that is the current value of postfix, and only then will thepostfix value be incremented.

The first trace of the second block uses the prefix increment, which first increments the variable before it is used in its expression. The result in this case is that 2 is traced to the Output panel. In both cases, though, you can see that the next time each variable is accessed it has its new value.

You will get a lot of mileage out of this operator, as well as from its companion, the decrement operator, which uses a double minus sign: postfix-- or --prefix. Where are these operators used most often? Loops! In fact, you can make the number tracing routine with fewer lines if you take even more advantage of this operator:

var number:uint = 1;
while(number <= 1000) {
trace(number++);
}

The while loop is often used when there is a condition to be met that is not easily managed by a fixed set of iterations but is more variable in nature. If a condition could be true for one iteration or a thousand iterations—and this will be determined by the contents of the loop—it would probably call for a while statement. I often use while loops to determine the nesting of objects in an application. For instance, to step through all the parent DisplayObjects of a movie clip named myClip, you might use a loop like the following one:

var clip:DisplayObject = myClip;
var parentClip:DisplayObject = clip.parent;
while (parentClip != null) {
trace(parentClip.name);
parentClip = parentClip.parent;
}

As long as the parent object is not null, Flash will trace its name to the Output panel and then check to see whether there is a parent higher up the display list hierarchy. The loop will continue to run until there are no more parent objects left, which occurs once the stage is reached that has no parent (being at the top of the display list).

The do . . . while loop

There is a variation of the while loop called the do...while loop:

do {
statements
} while (condition);

It is exactly the same as the while loop, except that the condition is evaluated at the end of each iteration instead of at the beginning. What this means in practice is that the statements in the loop are always executed at least once, even if the condition initially evaluates to false:

do {
trace("Hello");
} while (false);

To prove that the while and do...while loops are basically the same, you can rewrite the previous number-counting example as a do...while loop instead:

var number:uint = 1;
do {
trace(number++);
} while (number <= 1000);

All you really did here is to move the furniture about a bit and add a nice new side table in the form of the do keyword. In this case, it hasn’t made a single difference to the output. In your code, you should be aware of the subtle difference between while and do...while loops and use the appropriate one for your needs. Remember that while gives you zero or more iterations, and do...while gives you one or more, iterations, so do...while should be used in place of while when you need to ensure that the contents of the loop run at least one time.

The for Loop

The Grand Poobah of all loop statements is the for loop, which has several varieties. The one most commonly used allows you to initialize your loop control variable, specify the loop condition, and perform some action after every iteration, all in a single statement. It’s like one of those multitasking, slice-’n’-dice, bash-and-baste kitchen tools they’re always trying to peddle on the late-night shopping channels.

The for loop looks like this:

for (initializer; condition; action) {
statements
}

The initializer statement is executed only once before you start looping. Next, the condition is checked. If this evaluates to true, the statements in the body of the for loop are executed. The action statement is executed at the end of each iteration, after which the next iteration begins by evaluating the condition again. As you will see in the following example, the initializer statement plays an important part in defining how many times the loop will execute because the initializer variable increments on each loop until the condition variable is met.

Like the while loop, the for loop evaluates the condition at the start of each iteration. You would use a for loop when you are counting through a finite range of something, such as the number of characters in a string or the number of elements in an Array.

Using the for loop, you could rewrite the previous example like this:

for (var number:uint = 1; number <= 1000; number++) {
trace(number);
}

If you look closely, you can see that the various statements have shifted around, but they’re all there, and you get exactly the same output in the Output panel:

1
2
3
...
998
999
1000

Looping through an Array

The for loop is particularly handy for looping through all the values in an Array object. Actually, any of the loop statements would work, but the for loop was designed specifically to loop through sequences such as the elements in an array.

Earlier you created an array to hold the names of all the contacts in an imaginary address book. If you want to say hello to each of those contacts, you could write out a trace() statement for each of the contacts, but that would be both a waste of time and a code maintenance nightmare if you had 100 contacts in the address book.

Instead of messing around with 100 trace() statements, you could use a for loop to go over each of the contacts in the contactNames array, starting at index 0 and ending after the last one is processed. You know how many entries are in the address book by looking at the value ofcontactNames.length, so you now have all the information you need to create a for loop:

var contactNames:Array = ["Rod", "Jane", "Freddy"];
var numContacts:uint = contactNames.length;
for (var i:uint = 0; i < numContacts; i++) {
trace("Hello " + contactNames[i]);
}

When you’re using this loop, it doesn’t matter how many (or few) contacts you have in the address book—everyone gets a nice friendly greeting:

Hello Rod
Hello Jane
Hello Freddy

Image Note Remember that you are storing the length of the array in numContacts variables before the looping begins. The condition statement of the for loop is to run each iteration of the loop, so if you have any complex evaluation that occurs each iteration, it can slow things down. Now, retrieving the length of an array each iteration isn’t necessarily complex, but if you have a lot of loops and very long arrays, there can be a noticeable difference in your loops’ execution because Flash has to look up the value each iteration. It’s therefore best to store things such as an array’s length in a variable before the loop begins.

As you put arrays to work in your projects, you’ll find that they go hand in hand with for loops. Like its very own stalker, wherever there’s an array, a for loop is never far away.

More for Loops

In addition to the for loop discussed previously, there are two variations: the for in loop and the for each loop. These loops are used primarily for looping through all the elements in a complex object. I’ll discuss these loops in more detail later in the book as you work more with such objects, but their basic syntax is presented here:

for (var element:String in object) {
trace(object[element]);
}

for each (var element:Object in object) {
trace(element);
}

Breaking Out of a Loop

There are two basic ways to break out of a loop. One is the return statement, and it has more to do with functions than with loops, so I will leave it to the next section. The most common way to exit a loop prematurely (before all iterations are completed) is through the use of the breakstatement. Executing this at any point of a loop ends any further iterations and exits the loop. This is often used when some condition within the loop has been met and it is determined that further iterations are no longer needed. For instance, if you had an array of movie clips named clipsand you needed to find the clip named myClip, you could set up a for loop to iterate through an array and then exit the array once the clip has been found:

var clip:MovieClip;
var numClips:uint = clips.length;
for (var i:uint = 0; i < numClips; i++) {
if (clips[i].name == "myClip") {
clip = clips[i];
break;
}
}

Once the clip was found, no other loop iterations would be necessary, so you could break out of the loop.

A related command is continue, which causes a loop to immediately exit its current iteration and go to the next iteration. This is useful if, for instance, you are looping through an array and want to perform operations on only a single type of value, but skip other types of value. Consider the following example:

var integers:Array = [1, 5, -3, 5, 2, -1];
var numIntegers:uint = integers.length;
for (var i:uint = 0; i < numIntegers; i++) {
if (integers[i] < 0) {
continue;
}
// perform complex operations only on positive values
}

The continue statement causes the loop to continue to its next iteration every time a negative number in the array is detected. Positive numbers would not cause the loop iteration to exit and would have some complex operations (not defined here) performed on them.

Looping through a Vector

Looping through a vector is almost identical to an array, except that the iterator variable data type is known. This is especially convenient when using a for each loop.

var contactNames:Vector.<String> = new <String>["Rod", "Jane", "Freddy"];

for each (var contactName:String in contactNames) {
trace("Hello " + contactName);
}

Introducing Functions

At the very beginning of this chapter, you used the trace() function to send the value of a variable to the Output panel. I told you that a function was a reusable piece of code, and the good news is that you’re not restricted to the functions built into the Flash framework—you can actually create your own.

You’ll have realized by now that I’m rather fond of analogies, so indulge me while I rattle off another one. I’m forever losing my keys. I seem to find new and increasingly creative places to leave them—in a flowerpot or on top of the mirrored cabinet in the bathroom, for example. I could solve this problem by having 100 keys cut and placing them at strategic locations all over my apartment, and that would work just fine until I had to change the key (if I had to have the locks changed, for example.) I’d then have to have 100 copies made of the new key and go hunting around my apartment until I had found and replaced all copies of the old key—not how I want to spend my weekend.

A much better solution is to buy a key hook and always hang my keys there when I come in. I could then place sticky notes all over the apartment, reminding me that my keys are now hung on the back of the door. If I need to change the keys, I just change the one set hanging on the back of the door. The notes can stay because they point me only in the direction of my single set of keys.

Functions in your programs serve the same purpose. They collect functionality that is repeated throughout your code together under a name of your choosing and can then be used wherever necessary. If you ever need to change the functionality, all you have to do is update the code in your function.

Before you can make use of a function, you have to create it. A simple function definition takes the following form:

function functionName():returnType {
statements;
}

In the preceding example, functionName is the unique name for the function, returnType is the data type of whatever is returned by the function (which could be nothing—more on that in a bit), and contained within the curly braces is the list of ActionScript statements that will be executed whenever the function is called. When deciding on a name for your function, you need to respect the same rules as when defining a variable. A function name must

· Consist only of letters, digits, the underscore character, and the dollar symbol

· Not start with a number

· Not be a reserved word

· Be unique

Also, similar to variable names, your function names should reflect what the function does and follow some kind of convention to keep your naming consistent. To keep things simple, you’ll be using modified camel case notation for both function and variable names, which is exactly what ActionScript’s built-in functions use.

Image Note For the remainder of the examples in this chapter, you’ll no longer use the document class file to test the code (if you have been using it, not just placing code directly in the timeline). This is because as you introduce functions, it is easier to test the code directly in the timeline and not have to worry about some of the more complex issues such as scope and modifiers that would be required to test using a class file. These issues are covered in the next chapter, and you’ll return to using a document then. For now, you should create a new Flash file and enter all the following code directly on the timeline. Flex users can follow along in the text, but Flex versions of the code will not be presented. ­Unfortunately, with Flex, any exploration of functions is automatically an exploration of objects and classes, and that is a subject presented in the next chapter.

Creating a Function

Let’s say that there are several places in the code where you want to output the numbers 1 to 10 in the Output panel. Forgetting the fact that you’re unlikely to ever want to do this in a production project (stuff in the Output panel is visible only when viewing the SWF in the Flash IDE), you’d create a function something like this:

function countToTen():void {
for (var i:uint = 1; i <= 10; i++) {
trace(i);
}
}

Image Note Remember that this code should now go directly in your timeline, not in a separate class file.

You could then call this function using the function name followed by parentheses (as you did with trace()) wherever you need to in your code instead of copying and pasting the for loop several times:

trace("The numbers 1 to 10...");
countToTen();
trace("... again...");
countToTen();
trace("... and again...");
countToTen();

Now what the heck is that void that you have specified as a return type for the countToTen() function? Read on, young grasshopper!

Returning a Value from a Function

You can break all functions down into two groups, really: those that are supposed to return a value and those that are not. The countToTen() function is a good example of the latter, where it simply performs some action but does not return any value to the place in the code from where the function was called. You can call (or invoke) the function and let it run its course. In such cases, you must specify void as the return type for the function to let Flash know that the function is not intended to return any value.

If a function is supposed to return a value to the place in the code from where the function was called, then the function needs to include the return keyword followed by the data being returned:

return data;

What exactly is meant by “return a value?” Well, you have seen a function invoked without any values returned (countToTen()). When a function does return a value, at runtime it is as if the call to the function is replaced with the value returned by the function. For instance, if you had a function named getDayOfWeek() that returned the name of the current day of the week, the call to the function might appear as follows in the code:

var day:String = getDayOfWeek();

If when the movie is run, the getDayOfWeek() function determines that it is Tuesday and returns that value as a string, it is as if the line becomes the following at runtime:

var day:String = "Tuesday";

If a function is to return any data, when you create the function the data type for that data needs to be specified in the declaration. Take, for example, the following code, which contains a function to format the user’s name:

var firstName:String = "John";
var lastName:String = "Doe";

function getFullName():String {
var fullName:String = firstName + " " + lastName;
return fullName;
}

var userName:String = getFullName();
trace(userName);

The getFullName() function has been given the return type of String. Inside the function, you create a string variable and assign the combined values of the firstName and lastName variables created outside the function. This new variable, fullName, is then returned out of the function using the return keyword back to the place in the code from where the function was called.

Because the getFullName() function has a String return type, you can assign the result of this function to a new variable, userName, that is typed as String as well. If username had been declared as a Number, Flash would throw a compile-time error, and you would know that something was wrong—that you had tried to assign a string to a variable that was intended to hold a number.

Now, the return keyword does not necessarily have to appear at the end of a function and can be used to exit a function at any point. For instance, if you had a conditional within the function that returned different data based on the condition, you might have multiple returnstatements. This is often used when performing checks for validity before performing a function’s actions and works well because no further code in a function is run after a return statement is executed. Let’s look at an example of when and how this might be used:

var firstName:String;
var lastName:String;

function getFullName():String {
var fullName:String = firstName + " " + lastName;
return fullName;
}

var fullName:String = getFullName();
trace("name is: ", fullName);

You have modified the previous example so that no values are assigned to the firstName and ­lastName variables. If you test this movie now, you will see that the name is traced as null null. That isn’t right! What has happened is that a String variable, if undefined, will become null within any expression. You need to account for the fact that these variables might be undefined and return an empty string (no characters) from the function in that case.

This can be accomplished by combining a number of things covered in this chapter: conditionals, Boolean operations, logical negation, and the return statement. Try adding the following bold code to the previous example:

var firstName:String;
var lastName:String;

function getFullName():String {
if (!firstName || !lastName) {
return "";
}
var fullName:String = firstName + " " + lastName;
return fullName;
}

var fullName:String = getFullName();
trace("name is: ", fullName);
firstName = "John";
lastName = "Doe";
fullName = getFullName();
trace("name is: ", fullName);

The first line in the function is now a conditional statement that checks to see whether there are values assigned to the firstName or lastName variables. Any variable that is defined (and is not the number 0) will be evaluated as true within a Boolean expression, so placing the logical negation operator before a variable results in true only if the variable is not defined. To make it clearer, the preceding conditional could be expressed in English as follows: “If either the firstName variable is NOT defined OR the lastName variable is NOT defined, run these statements.” So if either variable is undefined, the contents of the if block are run.

Now, what exactly happens in the if block? Because you know that either one or both of the variables are undefined, there is no need to concatenate the values because that will return null null within the string. Instead, you use the return keyword to exit the function by returning an empty string. Once the return statement is run, the function is exited, and no further code is run. This is an important point because it allows you to exit the function when necessary while ensuring that further code is not executed.

If you want to exit a function that does not have a return type, you can use the return keyword by itself without any data following it. Take the following as an example:

var firstName:String;
var lastName:String;

function traceFullName():void {
if (!firstName || !lastName) {
return;
}
trace(firstName + " " + lastName);
}

traceFullName();
firstName = "John";
lastName = "Doe";
traceFullName();

Using Function Parameters

If you want the function to make use of values from outside of the function definition, you can pass these values in. In order to do so, you need to tell Flash what kind of information the function expects to be passed when the function is called.

You define the parameters (or arguments) for a function by placing them between the parentheses in the function definition. You can see how this fits into the overall function definition:

function functionName(parameters):returnType {
statements;
}

The list of parameters is comma separated, and each parameter has a name and a data type separated by a colon. If that sounds familiar, it’s because it’s very similar to how you define a variable, and that’s no accident—within the body of your function, the parameters are just extra variables that you can use in the statements to perform some task or other.

Let’s try an example, overhauling the earlier countToTen() function to count from 1 to a maximum number that you specify as a parameter:

function countTo(max:uint):void {
for (var i:uint = 1; i <= max; i++) {
trace(i);
}
}

You can now use the countTo() function to count from 1 to any number by passing that number in as part of the function call. You know how to do this already because you’ve been doing it with the trace() function—you specify the value you want to pass to the function between the parentheses in the function call:

countTo(5);
countTo(10);

Note that the max parameter is now required—you have to give the parameter a value when you’re calling the function or else Flash will tell you that you haven’t specified the correct number of arguments for the countTo() function. Sometimes this is undesirable, which is where default values for function parameters come in.

Providing a Default Value for Function Parameters

As you’ve seen, having to always pass a value for every parameter defined in the function definition isn’t always desirable. Sometimes you want to specify that particular parameters are optional and, if they are not given a value when the function is called, that they should adopt a predefined default value.

Suppose that you need to modify the countTo() function to count up to the specified maximum number but allow the starting number to optionally be specified when calling the function. If no starting value is specified, the function should start counting from 1:

function countTo(max:uint, min:uint = 1):void {
for (var i:uint = min; i <= max; i++) {
trace(i);
}
}

countTo(5);
countTo(10);

You can run the preceding example without changing the function calls because the second parameter, min, is optional and defaults to 1 if no value was specified. However, you can tell the second call to start counting from 6 by specifying the additional parameter value:

countTo(10, 6);

Although you can have as many optional parameters as you like, they can appear only at the end of the parameter list. The compiler will throw an error if you try to publish a Flash movie containing a function that has an optional parameter listed before a regular parameter in the parameter list.

Allowing for Variable Parameters

Because the number of arguments and their types need to be defined in the function definition (or signature, which consists of the function name, arguments, and return type), there is special syntax that must be used if you require functions to have a variable number of parameters passed in. When might you need such functionality? One example might be a sum() function, which adds any number of values and returns their sum. To create a function such as this that could accept any number of parameters, the ...(rest) parameter is required. Adding these three dots (like an ellipsis) to your function definition tells Flash that any number of values may be passed in from that point on in the function parameters. Each of those values is then placed into a single array that can be accessed using the name specified after the ...(rest) notation. Let’s take a look at how that sum() function might be written with this syntax:

function sum(...operands):Number {
var numOperands:uint = operands.length;
var total:Number = 0;
for (var i:uint = 0; i < numOperands; i++) {
total = total + operands[i];
}
return total;
}

trace(sum(1, 2, 3));
trace(sum(5, 10));

In the function definition, you specified that there may be any number of parameters passed in by using the ...(rest) syntax. However many this may be, they are placed into an array that you can reference using the name operands (because that is how you have defined it—any name can be used). Within the function, you determine the number of operands using the Array.length property and use a for loop to iterate through all the array’s elements, adding each value to the total. This total is returned from the function. The end result, as demonstrated by the two trace() statements, is that you can call sum() using different numbers of parameters without any errors.

One thing I want to introduce at this point is a shorthand way of taking a variable’s value, altering it, and reassigning it to the same variable. This was done in the last example with the following line:

total = total + operands[i];

Here, the value of total was taken and added to the value of the current operand, and the result was placed back into total. Whenever such an operation occurs, the shorthand way of writing the exact same thing is the following:

total += operands[i];

When an arithmetic operator is followed by the assignment operator, the variable to the left of the operators has its value operated upon, along with the operand to the right of the operators, with the calculated result assigned directly back to the variable. Here are a few more examples to help demonstrate:

var number:uint = 2;
number += 5; // results in 7 now being assigned to number
number -= 3; // results in 4 now being assigned to number
number *= 2; // results in 8 now being assigned to number

The same operation can be used with the concatenation operator (+) with strings:

var name:String = "John";
name += " Doe"; // results in name now holding "John Doe"

You will see this syntax a lot in code, and you will be using it from here on out in the text.

Passing Values and References

One very important item to discuss, and one that is a frequent stumbling block for new programmers, is the difference between passing variables by value and passing variables by reference. As a rule, any variable containing a primitive data type—such as numbers, strings, and Boolean values—will pass only its value but no reference to itself, while a complex data type, such as an array, will pass its reference. The easiest way to present this, before discussing it in relation to functions, is to look at simple variable assignments.

Take as an example the following code:

var original:uint = 1;
var copy:uint = original;
trace(original, copy); // outputs 1 1
original = 2;
trace(original, copy); // outputs 2 1

Here, a variable original is initialized and assigned the value of 1. A second variable, copy, is then initialized and given the value of original. Tracing these values produces the expected result 1 1. On the next line, the value of original is changed to 2, and when both are traced again, the result is 2 1. As you can see, although the original variable’s value was changed, it had no effect on the copy variable. This is because when the value was initially assigned to copy, no reference to original was made; only its value was retrieved and stored incopy. No connection is ever made between original and copy, so the value of either can change without any effect on the other.

With arrays and other complex objects, it is not the value that is passed, but instead a reference to the place in memory where the object is stored. Altering the variable then alters the object in memory that the variable was pointing to, which means that altering one variable alters all others that reference the same object. That’s a pretty heady concept, so it’s definitely time for an example:

var original:Array = [1, 2, 3];
var copy:Array = original;
trace(original); // outputs 1,2,3
trace(copy); // outputs 1,2,3
original[1] = 50;
trace(original); // outputs 1,50,3
trace(copy); // outputs 1,50,3

You have a similar setup to the last example. The variable original is initialized and assigned an array of three values. copy is then assigned the value of original. At this point, original and copy are just pointing to the same place in memory. When these arrays are traced, the result is that both output 1,2,3. You then change the value of the second index in original and trace out both variables once more. Because both variables point to a single array, altering one alters the other as well. More precisely, altering one alters the array stored in memory, so that when each variable is sent to the trace method, Flash looks up the current value of the array and outputs it. In both cases, the value output is 1,50,3.

So a variable with a primitive data type is passed by value, and a variable with a complex data type is passed by reference. How does this apply to functions? Well, if a variable with a primitive data type is passed to a function, only its value is passed into the body of the function. Altering that value inside the function will have no effect on the original variable. Consider the following example:

function square(operand:Number):Number {
return (operand * operand);
}

var number:Number = 5;
trace(square(number)); // outputs 25
trace(number); // outputs 5

The function square() takes a single operand and returns the product of that number multiplied by itself. The first trace() statement outputs 25, as expected. The second trace() statement outputs 5, the original value of number, because the variable is unchanged by the function. This is because for a variable containing a primitive value such as a number, only the value is passed to the function. The function can do whatever it likes to the value without any effect on the original variable. This is the same for both strings and Boolean values.

If you wanted to change the value of number based on the results of the function, you would need to assign the returned value to number after the function is invoked, as in the following (which uses exactly the same function):

var number:Number = 5;
number = square(number);
trace(number); // outputs 25

In this case, the number variable is assigned the result of the square() function performed on number, so tracing its value after the fact produces 25.

Things change a bit when dealing with complex objects such as arrays. In the case of an array (which is the only complex object you’ve dealt with so far), it is passed by reference to the function, so it is the reference to the array in memory that exists within the body of the function. Altering any value in this reference alters the array, so it alters any other references to the array that exist. Take a look at the following code, which demonstrates the effect:

function doubleAllValues(array:Array):void {
var numItems:uint = array.length;
for (var i:uint = 0; i < numItems; i++) {
array[i] *= 2;
}
}

var myArray:Array = [1, 2, 3];
trace(myArray); // outputs 1,2,3
doubleAllValues(myArray);
trace(myArray); // outputs 2,4,6

Here, you create a function doubleAllValues(), which iterates through an array and doubles the value stored in each index. To test this, you create a new array with the values 1,2,3 (which the trace() statement verifies). You then pass this array to the doubleAllValues()function. When you trace the array a second time, you find the values are now 2,4,6 because these values were altered within the body of the function. This is the result of having passed the array by reference.

Function Scope

The last item I’ll address at this time is function scope, which is another issue that often causes frustration for new programmers. All use of variables thus far has been within the scope of the main timeline. With the examples, you have not had to worry about whether variables existed within the scope of a function because all variables have been available. This is not always the case, however.

Variables are accessible only within the scope in which they were declared. Each function actually has its own scope. That means that any variable that is declared within a function is accessible only within that function. It is referred to as a local variable. Once the function completes, the variable will no longer exist. Take, for example, the following:

function createVariable():void {
var myVariable:uint = 5;
}
createVariable();
trace(myVariable);

If you try to run this code, you will get a compile-time error that states Access of undefined property myVariable because you are trying to access a variable that has been defined only within the scope of the createVariable() function. It is only within this function that the variable is initialized and assigned a value. Once the function completes, the scope of the function is terminated, and the variable is no more. Attempting to access it outside of the scope in which it existed causes the error. If you alter the code slightly, you get something that will compile as follows:

function createVariable():void {
myVariable = 5;
}
var myVariable:uint;
createVariable();
trace(myVariable); // outputs 5

Because now you have declared the variable outside of the scope of the function on the main timeline, you no longer get the error. Because the createVariable() function exists within the scope of the main timeline as well, it has access to all the variables declared on the main timeline, which includes myVariable.

What happens if you initialize a variable within one scope (a function, perhaps) that already exists in another scope (such as the main timeline)? Let’s take a look:

function createVariable():void {
var myVariable:uint = 5;
trace("inside function:", myVariable);
}
var myVariable:uint = 10;
createVariable();
trace("main timeline: ", myVariable);

The output of these lines follows:

inside function: 5
main timeline: 10

In this code, you are assigning a value (10) to myVariable on the main timeline. However, within the function, you are also creating a myVariable and assigning it a value of 5. The trace() inside the function results in 5 being output. The trace() on the main timeline outputs10. This is because within the function, the locally declared myVariable takes precedence over any declared outside of the function’s scope. Back on the main timeline, the value of 10 is traced out because the myVariable that existed locally within the function’s scope was destroyed when the function was completed—the main timeline does not have access to any variables that were created within the scope of the function.

Taking this a step further, because local variables within a function are destroyed upon completion of a function, it follows that if you want a value to persist between calls to a function, it must therefore be declared outside of the function, as demonstrated in the following:

function buy(price:Number):void {
total += price;
}
var total:uint = 0;
buy(1.25);
buy(5.50);
buy(10.75);
trace(total); // outputs 16

Only because you have declared total outside of the scope of the buy() function can you continue to add to it each time the function is called.

Commenting Your Code

Before you leave this chapter, I want to talk to you about comments. Comments in a block of program code are there to help you, the developer, and the people you work with understand what a particular block of code is intended to do and can even be used to generate helpful documentation. This may sound odd at first; surely it’s the computer that needs to understand what the code does. You already know what it does because you wrote it. Well, that may be true when you’re writing the code, but will you remember what it’s supposed to do tomorrow, next week, or next month when you have to come back and modify it? Maybe—if you’ve got a brain like Albert Einstein—but the chances are that you will have moved on to new projects and won’t remember a darn thing. Or worse, someone else can come onto a project after you have left and have no idea what your intention was with the uncommented code, which slows down development and can give you a bad reputation as the original author of the code.

Take it from me; you don’t want to have to trawl through 500-plus lines of ActionScript code on a Monday morning to try to work out exactly what it was that you or someone else was trying to do.

There are two types of comments in ActionScript 3.0: the line comment and the block comment. The line comment, as its name suggests, creates a comment that spans a single line in your code. A line comment starts with a double forward slash, //, and ends at the end of the line:

// Hello, I am a line comment, and I eat peanut butter on toast

A block comment can span multiple lines. It starts with a forward slash followed by an asterisk, /*, and ends with an asterisk followed by a forward slash, */:

/* Hello, I am a block comment,
and I eat line comments for breakfast */

Comments can be inserted almost anywhere in your code: at the start of the file, between two lines of code, on the same line as a piece of code, at the end of the file—wherever you like. The exceptions to this rule are that you can’t have a comment in a string literal because the comment is interpreted as part of the string, and you can’t have a block comment within another block comment.

In addition to helping you understand your code, comments can also be used to temporarily disable parts of your code. When code appears within a comment, either after a line comment marker on the same line or between block comment delimiters, that code will not be executed by the Flash Player. So you can add as many useful comments as you want because it will not affect the end size of your SWF file.

Bad vs. Good Comments

Given the previous commenting advice, you would be forgiven for thinking that peppering your code with as many comments as you can is a good idea. However, comments are useful only if they tell you more than a quick glance at the code would, and even then only as long as they remain up to date. For example, take the following snippet of code:

// Set matchFound to false
var matchFound:Boolean = false;

The line of code in the snippet creates a new Boolean variable named matchFound and sets its initial value to false. The comment above the line of code tells you exactly the same information, and a comment like that is no good to anyone and just bloats the code. Comments should generally be at a higher level of abstraction than the code. That is, they shouldn’t attempt to tell you how something will be done but why it is being done. A better comment for the previous line might be the following:

// Assume that no match has been found
var matchFound:Boolean = false;

Now the comment tells you why the matchFound variable is being set to false, which wasn’t easy to glean from looking at the line of code itself.

Beware of comments that become incorrect because the code around them has been updated. There’s nothing more confusing than to read a comment and assume that a block of code does one thing when, in fact, it does the complete opposite:

// Assume that no match has been found
var matchFound:Boolean = true;

When you modify your code, be sure to keep the comments updated, too.

Commenting for Documentation

One great result of having comments in your code is that if done with the proper syntax, those comments can be used to generate documentation. Adobe has ASDoc, a command-line tool that ships with the free Flex Software Development Kit (SDK) and can be used to generate documentation from code files that use a special comment syntax. As an example of the syntax, one of the functions might have the following comments:

/**
* This function takes a single numeric operand
* and returns the value squared.
*
* @param operand The number to square.
*
* @returns The squared value of the specified number.
*/
function square(operand:Number):Number {
return (operand * operand);
}

An ASDoc comment begins with the notation /** and ends with a closing */. Within the comment block, in addition to a description placed at the top (which can use HTML formatting), there are tags that you can use that contain special meaning. For instance, the tag @param is used to describe any parameters that are to be passed to a function. The @returns tag is used to describe what is returned from a function. By placing them in front of data, you let the ASDoc tool know how to place the comments within the documentation.

There is a lot more to know about ASDoc; not only additional tags but also how to run the command-line tool to generate the documentation. (Although it is beyond the scope of this book, it is covered in detail in the Adobe documentation.) I present it here because it is a standard way to comment code (even outside the ActionScript world). It’s based on industry standard documenting practice, and you’ll undoubtedly come across such syntax as you program more. Commenting in a similar fashion is certainly a good habit to get into as you begin to program.

Summary

I’ve covered a monumental amount of ground in this chapter, so give yourself a hearty pat on the back if you’re still with me. I feel like a particularly cruel drill sergeant putting you through this so early on, but now that the basics are behind you, you’re almost ready to start having some serious fun.

This chapter looked at the very basic building blocks of the ActionScript language, from variables to constants, loops to functions, and beyond. Along the way, I tried to dispense what I know about best coding practices so that you’re not only writing code that works but also code that you can maintain when you come back to it in six months’ time.

A lot of the examples were necessarily contrived to not let too much get in the way. If some of the concepts are still a bit fuzzy in your head, I advise that you carry on regardless, skipping back here if any of the basic concepts continue to be a bit blurry.

That’s the good news. The bad news is that you’ve got one more brain-busting chapter to go before you get to the really cool stuff, and it’s a real doozy. Unless you’re eager to get going, I’d suggest you give yourself a bit of a breather before carrying on. Go out into the big wide world and take a few gulps of good, old-fashioned fresh air to clear your head. One of the biggest mistakes you can make when learning a new subject is to try and force your brain to digest too much information in one go, and the next chapter on objects and classes in ActionScript is particularly important—I need your brain to suck it up like a sponge.

See you in Chapter 3 when you’re ready.