Requirements

Prerequisite knowledge

You should be familiar with ActionScript 3 syntax, data types, and variables. Some understanding of operators and math is useful but not required.

User level

Beginning

Functions are one of the most common and effective ways to organize your code into manageable and understandable blocks. These blocks can then be reused throughout your application resulting in simpler and more maintainable code. In this article, you will learn what a function is and how to execute the code contained within it. You will also learn about optional components of a function including parameters and return values. Finally you will learn about function scope and how functions can be defined either at compile-time or runtime in ActionScript 3.

Functions

Functions are named blocks of code that carry out specific tasks and can be reused in your program. There are two types of functions in ActionScript 3: methods and function closures. The context in which the function is defined determines whether a function is a called a method or a function. A function is called a method if you define it as part of a class definition or attach it to an instance of an object. A function is called a function if it is defined in any other way.

Keep in mind that a good function does only one task. When a function performs multiple tasks, it becomes difficult to debug and its reusability is reduced.

For example, pretend you are developing an application that allows the user to select which shape to draw and the shape's color and then draws the user's selection on the screen. You should write five functions:

  • A function to ask the user to select a shape
  • A function to handle the data of the user's shape selection
  • A function to ask the user to select a color
  • A function to handle the data of the user's color selection
  • A function to use the shape and color data to draw the selection on the screen

Could you put all of the code into one function? Technically, yes. But what happens when you test the application and nothing gets drawn on the screen? Which part of your one long function doesn't work? By writing five separate functions, you could easily test each function individually to find the bug. What if you decide that one of the shapes does not have a color selection option? If you had written one long function, you must rewrite the entire function to change it. With separate functions, you could choose not call the color selection function when the user selects that one shape. Keeping your functions focused on a single task makes your life as a programmer easier.

Defining functions

Creating a function is called function definition. ActionScript 3 requires the use of a keyword—function—to signal that you are defining a function. Include the following six parts to define a function in ActionScript 3:

  1. access control attribute keyword
  2. function
  3. function name
  4. function parameters, in a comma-delimited list enclosed in parentheses (optional)
  5. return type
  6. function body—the ActionScript code to be executed when the function is called, enclosed in curly brackets

The following code defines a function named myTraceFunction that does not return any data. This function does not have a parameter.

private function myTraceFunction():void{ trace(“Hello world”); } myTraceFunction(); // Hello world

The following code defines a function named myMathFunction that does return an integer. This function requires a parameter to complete the equation.

public function myMathFunction(intParameter:int):int{ return(intParameter * 5); } myMathFunction(5); //returns the int value 25

The following code defines a function named anotherMathFunction that returns an integer. This function has an optional parameter with a default value of 2. The first function call shown does not pass a value, therefore, the default value is used. The second function call does pass a value.

private function anotherMathFunction(intParamter:int = 2):int{ return(intParameter * 10); } anotherMathFunction(); //returns the int value 20 anotherMathFunction(5); //retunrs the int value 50

Calling functions

A function doesn't do anything until it is called. The computer only executes the code inside the { } when the function is called. You call a function by using its name followed by the parentheses operator ( () ). You use the parentheses operator to enclose any function arguments you want to send to the function. For example, the trace() function is a top-level function in ActionScript 3. It displays the parameter passed to it in the console window when the code is debugged:

trace(“Use trace to help debug your code”);

If you are calling a function with no parameters, an empty pair of parentheses is required. For example, use the Math.random() method, which takes no parameters, to generate a random number:

var randomNum:Number = Math.random();

Function parameters and arguments

Sometimes functions need data to successfully complete their defined tasks. When defining a function, the needed data is referred to as a parameter. When the data is being used within the function body, it is also referred to as a parameter. The actual data sent to a function at the time of a function call is referred to as an argument. Two different names are used to distinguish where the data is.

To create parameters for a function, declare a list of parameters and their data types in the parenthesis in a function definition. Separate the parameters with commas. Not all functions require data—only declare parameters when a function needs data to complete its task.

If a function has parameters defined, providing arguments at the time the function is called is required.

Default parameter values

In ActionScript 3, you can declare default parameter values for a function. If you assign a value to the parameter in the function definition, the parameter becomes optional. If a call to a function with default parameter values omits a parameter with a default value, the default value for that parameter is used. The values assigned as default values must be compile-time constants. List optional parameters after required parameters in the parameter list.

For example, the following code creates a function with three parameters, two of which have default values. When the function is called with only one parameter, the default values for the parameters are used.

private function optionalParameterExample(x:int, y:int = 3, z:int = 5):void { trace(x, y, z); } optionalParameterExample(1); // 1 3 5

Passing arguments by value or reference

Primitive values—Boolean, Number, int, uint, and String—are passed by value into a function. When an argument is passed by value, the value is copied into a local variable for use within the function. The original value is unaffected and remains unchanged regardless of what happens within the function.

For example, the following code creates a function named passPrimitives() that defines two parameters named firstPrimParam , an int, and secondPrimParam , a String. The function is called with the arguments firstPrimValue and secondPrimValue . Because the arguments are primitives, they are passed by value. Within the passPrimitives() function, the value of firstPrimParam is incremented and the value of secondPrimParam appends string characters. The values of firstPrimValue and secondPrimValue are unaffected as shown in the last trace statement.

public function passPrimitives(firstPrimParam:int, secondPrimParam:String):void{ firstPrimParam++; secondPrimParam+=”test”; trace(firstPrimParam, secondPrimParam); } var firstPrimValue:int = 10; var secondPrimValue:String = “Hello world”; trace(firstPrimValue, secondPrimValue); // 10 Hello world passPrimitives(firstPrimValue, secondPrimValue); // 11 Hello world test trace(firstPrimValue, secondPrimValue); // 10 Hello world

Complex data types are passed by reference into a function. When an argument is passed by reference, only a reference to the argument is passed. A copy of the actual argument is not made. When the function runs, the code in the function body will change the object that is passed.

For example, the following code creates an object named objVar with two properties, x and y . The object is passed as an argument to the passByRef() function. Because the object is not a primitive type, the object is passed by reference. Changes made to the parameters within the function affect the object properties outside the function.

public function passByRef(objParam:Object):void { objParam.x++; objParam.y++; trace(objParam.x, objParam.y); } var objVar:Object = {x:10, y:15}; trace(objVar.x, objVar.y); // 10 15 passByRef(objVar); // 11 16 trace(objVar.x, objVar.y); // 11 16

The objParam parameter references the same object as the global objVar variable. As you can see from the trace statements in the example, changes to the x and y properties of the objParam object are reflected in the objVar object.

The ...(rest) parameter

The ...(rest) parameter accepts a variable number of arguments which will be stored as an Array. Follow ...(rest) with the name of the argument list. Use that name in the function body. This parameter declaration must be the last parameter specified.

The following example shows the traceArgs() function using the ...(rest) parameter.

public function traceArgs(... args):void { for (var i:int = 0; i < args.length; i++){ trace(args[i]); } } traceArgs(10, 25, 40); // output: // 10 // 25 // 40

The ...(rest) parameter can also be used with other parameters, as long as it is the last parameter listed. The following example modifies the traceArgs() function so that its first parameter, firstParam , is of type int, and the second parameter uses the ... parameter. The output does not include the first value, because the first argument is no longer part of the array created by the ...(rest) parameter.

public function traceArgs(firstParam:int, ... args){ for (var i:int = 0; i < args.length; i++){ trace(args[i]); } } traceArgs(10, 25, 40); // output: // 25 // 40

Returning values from functions

private function myTraceFunction():void{ trace(“Hello world”); } myTraceFunction(); // Hello world

To return a value from your function, use the return statement followed by the expression or literal value that you want to return. For example, the following code returns an expression representing the parameter:

public function doubledValue(baseNum:int):int { return (baseNum * 2); }

The return statement terminates the function. Any statements written after a return statement are not executed, as follows:

public function doubledValue(baseNum:int):int { return (baseNum * 2); trace("after return"); // This trace statement will not be executed. }

Function scope

In ActionScript, all variables and functions exist within a specific scope. Scope determines a variable's or function's accessibility from different parts of the program. If your code attempts to access a variable or function that is out of scope, the compiler will not recognize it and throw an error. Variables or functions that have a global scope are accessible from anywhere in the code. Local scope limits accessibility to within the scope in which the variable or function is defined.

Function closures

A function closure is an object that contains a snapshot of a function and its lexical environment. A function's lexical environment includes all the variables, properties, methods, and objects in the function's scope chain, along with their values. Function closures are created any time a function is executed apart from an object or a class. Because function closures retain the scope in which they were defined, interesting results occur when a function is passed as an argument into a different scope.

For example, the following code creates two functions: foo(), which returns a nested function named rectArea() that calculates the area of a rectangle, and bar() , which calls foo() and stores the returned function closure in a variable named myProduct . Even though the bar() function defines its own local variable x (with a value of 2), when the function closure myProduct() is called, it retains the variable x (with a value of 40) defined in function foo() . The bar() function therefore returns the value 160 instead of 8 .

function nagCoWorker(name:String, message:String, nagInterval:Number ):void { setInterval( function() { trace( name + ", " + message ); } nagInterval); } nagCoWorker( "Lee", "Hurry Up!", 500 ); nagCoWorker( "Alan", "Stay Awake", 1000 ); //Output: Lee, Hurry Up! Alan, Stay Awake Lee, Hurry Up! Lee, Hurry Up! Alan, Stay Awake Lee, Hurry Up! Lee, Hurry Up! Alan, Stay Awake

Functions as objects

Functions passed as arguments to another function are passed by reference and not by value. When you pass a function as an argument, you use only the identifier and not the parentheses operator that you use to call the method. For example, the following code passes a function named clickListener() as an argument to the addEventListener() method:

addEventListener(MouseEvent.CLICK, clickListener);

Functions have properties and methods, just as any other object can. Every function has a read-only property named length that stores the number of parameters defined for the function. The code below shows the length property being used.

function traceLength(x:uint, y:uint):void { trace("arguments expected: " + traceLength.length); } traceLength(3, 5); // output: arguments expected: 2

Anonymous functions

ActionScript supports anonymous functions (also called function expressions). These functions are called anonymous because they have no name. Anonymous functions were widely used in versions of ActionScript before version 3.

Creating anonymous functions

Creating an anonymous function and storing it in a variable is similar to defining a function statement. Include the following nine parts to define an anonymous function in ActionScript 3:

  1. var
  2. variable name
  3. Colon operator :
  4. Function class to indicate the data type
  5. The assignment operator =
  6. function
  7. function parameters, in a comma-delimited list enclosed in parentheses (optional)
  8. return type
  9. function body—the ActionScript code to be executed when the function is called, enclosed in curly brackets

In the following example, an anonymous function is assigned to a variable named traceParameter :

traceParameter: var traceParameter:Function = function (aParam:String){ trace(aParam); } traceParameter("hello"); // hello

Choosing between function statements and anonymous functions

Unlike defined functions (also called function statements), anonymous functions are expressions rather than statements. Therefore, an anonymous function cannot stand on its own as a function statement can. It can only be used as a part of a statement, usually an assignment statement. A summary of the difference between anonymous functions and defined functions is in the following table.

Table 1. Comparing anonymous and defined functions

Anonymous functions

Defined functions

Cannot be used as a method

Can be used as a method of an object

Exists only in the scope in which it is defined

Exists within the object it is defined in

Can only be called in the scope in which it is defined

Can be called at any point in the code

Can be reassigned a new value or deleted

Cannot be deleted or changed

As a rule, use a function statement unless specific circumstances call for the use of an expression. Function statements are easier to read than assignment statements that contain function expressions. Function statements make your code more concise; they are less confusing than function expressions, which require you to use both the var and function keywords.

There are some circumstances in which anonymous functions are useful. Use an anonymous function for functions that are used only once and then discarded. If the functionality of a function must change at runtime, use an anonymous function. If a function is only useful within another function, use an anonymous function. When working in a functional programming paradigm, use anonymous functions.

Take into account two subtle differences between defined functions and anonymous functions when choosing which technique to use. First, anonymous functions do not exist independently as objects with regard to memory management and garbage collection. If the object to which an anonymous function is attached goes out of scope, you no longer have access to the anonymous function. If the object is deleted, the memory that the anonymous function uses becomes eligible for garbage collection.

Second, defined functions exist throughout the scope in which they are defined, including in statements that appear before the function definition. Anonymous functions are defined only for subsequent statements. For example, the following code successfully calls the scopeTest() function before it is defined:

statementTest(); // statementTest public function statementTest():void { trace("statementTest"); }

Anonymous functions are not available before they are defined, so the following code results in a runtime error:

expressionTest(); // run-time error var expressionTest:Function = function ():void{ trace("expressionTest"); }

Where to go from here

As you have seen in this article, functions give you a way to capture common functionality and locate it into a single, reusable block of code. Functions take on even more importance when combined with classes to form reusable and encapsulated objects. Begin learning about objects and classes in ActionScript 3 by reading Introduction to objects, Introduction to Classes, and Writing classes in ActionScript 3 (all coming October 31).

Acknowledgement

The content in this article is based on material originally published in the Learning ActionScript 3 user guide created by Adobe Community Help and Learning.