Function parameters

ActionScript 3.0 provides some functionality for function parameters that may seem novel for programmers new to the language. Although the idea of passing parameters by value or reference should be familiar to most programmers, the arguments object and the ... (rest)parameter may be new to many of you.

Passing arguments by value or by reference

In many programming languages, it’s important to understand the distinction between passing arguments by value or by reference; the distinction can affect the way code is designed.

To be passed by value means that the value of the argument is copied into a local variable for use within the function. To be passed by reference means that only a reference to the argument is passed instead of the actual value. No copy of the actual argument is made. Instead, a reference to the variable passed as an argument is created and assigned to a local variable for use within the function. As a reference to a variable outside the function, the local variable gives you the ability to change the value of the original variable.

In ActionScript 3.0, all arguments are passed by reference, because all values are stored as objects. However, objects that belong to the primitive data types, which includes Boolean, Number, int, uint, and String, have special operators that make them behave as if they were passed by value. For example, the following code creates a function named passPrimitives() that defines two parameters named xParam and yParam , both of type int. These parameters are similar to local variables declared inside the body of the passPrimitives() function. When the function is called with the arguments xValue and yValue , the parameters xParam and yParam are initialized with references to the int objects represented by xValue and yValue . Because the arguments are primitives, they behave as if passed by value. Although xParam and yParam initially contain only references to the xValue and yValue objects, any changes to the variables within the function body generate new copies of the values in memory.

function passPrimitives(xParam:int, yParam:int):void 
{ 
    xParam++; 
    yParam++; 
    trace(xParam, yParam); 
} 
 
var xValue:int = 10; 
var yValue:int = 15; 
trace(xValue, yValue);// 10 15 
passPrimitives(xValue, yValue); // 11 16 
trace(xValue, yValue);// 10 15

Within the passPrimitives() function, the values of xParam and yParam are incremented, but this does not affect the values of xValue and yValue , as shown in the last trace statement. This would be true even if the parameters were named identically to the variables, xValue and yValue , because the xValue and yValue inside the function would point to new locations in memory that exist separately from the variables of the same name outside the function.

All other objects—that is, objects that do not belong to the primitive data types—are always passed by reference, which gives you ability to change the value of the original variable. 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 not only passed by reference, but also stays a reference. This means that changes made to the parameters within the function will affect the object properties outside the function.

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.

Default parameter values

New in ActionScript 3.0 is the ability to declare default parameter values for a function. If a call to a function with default parameter values omits a parameter with default values, the value specified in the function definition for that parameter is used. All parameters with default values must be placed at the end of the parameter list. The values assigned as default values must be compile-time constants. The existence of a default value for a parameter effectively makes that parameter an optional parameter . A parameter without a default value is considered a required parameter .

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.

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

The arguments object

When parameters are passed to a function, you can use the arguments object to access information about the parameters passed to your function. Some important aspects of the arguments object include the following:

  • The arguments object is an array that includes all the parameters passed to the function.

  • The arguments.length property reports the number of parameters passed to the function.

  • The arguments.callee property provides a reference to the function itself, which is useful for recursive calls to function expressions.

    Note: The arguments object is not available if any parameter is named arguments or if you use the ... (rest) parameter.

    If the the arguments object is referenced in the body of a function, ActionScript 3.0 allows function calls to include more parameters than those defined in the function definition, but will generate a compiler error in strict mode if the number of parameters doesn’t match the number of required parameters (and optionally, any optional parameters). You can use the array aspect of the arguments object to access any parameter passed to the function, whether or not that parameter is defined in the function definition. The following example, which only compiles in standard mode, uses the arguments array along with the arguments.length property to trace all the parameters passed to the traceArgArray() function:

    function traceArgArray(x:int):void 
    { 
        for (var i:uint = 0; i < arguments.length; i++) 
        { 
            trace(arguments[i]); 
        } 
    } 
     
    traceArgArray(1, 2, 3); 
     
    // output: 
    // 1 
    // 2 
    // 3
    

    The arguments.callee property is often used in anonymous functions to create recursion. You can use it to add flexibility to your code. If the name of a recursive function changes over the course of your development cycle, you need not worry about changing the recursive call in your function body if you use arguments.callee instead of the function name. The arguments.callee property is used in the following function expression to enable recursion:

    var factorial:Function = function (x:uint) 
    { 
        if(x == 0) 
        { 
            return 1; 
        } 
        else 
        { 
            return (x * arguments.callee(x - 1)); 
        } 
    } 
     
    trace(factorial(5)); // 120
    

    If you use the ... (rest) parameter in your function declaration, the arguments object will not be available to you. Instead, you must access the parameters using the parameter names that you declared for them.

    You should also be careful to avoid using the string "arguments" as a parameter name, because it will shadow the arguments object. For example, if the function traceArgArray() is rewritten so that an arguments parameter is added, the references to arguments in the function body refer to the parameter rather than the arguments object. The following code produces no output:

    function traceArgArray(x:int, arguments:int):void 
    { 
        for (var i:uint = 0; i < arguments.length; i++) 
        { 
            trace(arguments[i]); 
        } 
    } 
     
    traceArgArray(1, 2, 3); 
     
    // no output
    

    The arguments object in previous versions of ActionScript also contained a property named caller , which is a reference to the function that called the current function. The caller property is not present in ActionScript 3.0, but if you need a reference to the calling function, you can alter the calling function so that it passes an extra parameter that is a reference to itself.

The ... (rest) parameter

ActionScript 3.0 introduces a new parameter declaration called the ... (rest) parameter. This parameter allows you to specify an array parameter that accepts any number of comma- delimited arguments. The parameter can have any name that is not a reserved word. This parameter declaration must be the last parameter specified. Use of this parameter makes the arguments object unavailable. Although the ... (rest) parameter gives you the same functionality as the arguments array and arguments.length property, it does not provide functionality similar to that provided by arguments.callee . You should ensure that you do not need to use arguments.callee before using the ... (rest) parameter.

The following example rewrites the traceArgArray() function using the ... (rest) parameter instead of the arguments object:

function traceArgArray(... args):void 
{ 
    for (var i:uint = 0; i < args.length; i++) 
    { 
        trace(args[i]); 
    } 
} 
 
traceArgArray(1, 2, 3); 
 
// output: 
// 1 
// 2 
// 3

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

function traceArgArray(x: int, ... args) 
{ 
    for (var i:uint = 0; i < args.length; i++) 
    { 
        trace(args[i]); 
    } 
} 
 
traceArgArray(1, 2, 3); 
 
// output: 
// 2 
// 3