Table of Contents

9.8 Function Parameters Revisited

Now that we're comfortable with how functions work, let's return to the topic of function parameters. Our current discussion requires a little knowledge of objects, so new programmers may want to read Chapter 12 before reading this section.

9.8.1 Number of Parameters

Earlier we saw that the parameters of a function are declared when the function is created. Recall the syntax:

function funcName (param1, param2, ...paramn) {
  statements
}

Perhaps surprisingly, the number of parameters passed to a function can differ from the number specified in the formal function declaration. Functions can accept any number of parameters, whether more than or fewer than the "expected" number. When a function is called with fewer than the declared number of parameters, the value of each missing parameter is set to undefined. For example:

function viewVars (x, y, z) {
  trace ("x is " + x);
  trace ("y is " + y);
  trace ("z is " + z);
}
viewVars(10);  // In Flash Player 6, displays: 
               // x is 10
               // y is undefined
               // z is undefined
               // (In Flash Player 5, undefined variables are displayed as a
               // blank string in the Output window.)

When a function is called with more parameters than the declared number, excess parameter values can be accessed using the arguments object. (Obviously, the excess parameters can't be accessed by name, as explicitly declared parameters can, because their names were not declared.)

9.8.2 The arguments Object

During the execution of any function, the built-in arguments object gives us access to the following:

The arguments object is really a special hybrid between an array and an object with some other properties. In Flash 5, arguments was not an array instance. In Flash MX, however, arguments is an instance of the Array class and therefore supports Array's methods and properties.

9.8.2.1 Retrieving parameter values from the arguments array

The arguments array lets us check the value of any function invocation argument, whether or not that parameter is defined formally in the function's declaration statement. To access a parameter, we examine the indexes of the arguments array:

arguments[n]

where n is the index of the argument we're accessing. The first argument (the leftmost argument in the function-call invocation) is stored at index 0 and is referred to as arguments[0]. Subsequent arguments are stored in order, proceeding to the right—so, the second argument is arguments[1], the third is arguments[2], and so on.

From within a function, we can tell how many arguments were passed to the currently executing function by checking the number of elements in arguments, as follows:

numArgs = arguments.length;

We can easily cycle through all the arguments passed to a function and display the results in the Output window, as shown in Example 9-3.

Example 9-3. Displaying an unknown number of arguments
function showArgs () {
  for (var i = 0; i < arguments.length; i++) {
    trace("Argument " + (i + 1) + " is " + arguments[i]);
  }
}
showArgs(123, 23, "skip intro");
// Displays...
Argument 1 is 123
Argument 2 is 23
Argument 3 is skip intro

The arguments array allows us to create very flexible functions that accept an arbitrary number of arguments.

Here's a generic function that removes any number of duplicated movie clip instances from the Stage:

function killClip () {
  for (var i = 0; i < arguments.length; i++) {
    arguments[i].removeMovieClip();
  }
}
killClip(clip10, clip5, clip13);

Reader Exercise: Modify our earlier combine( ) function to accept an arbitrary number of inputs. What other functions might benefit from accepting an arbitrary number of parameters? How about a function that averages a list of numbers? (Hint: sum all the arguments and then divide by the number of arguments.)

9.8.2.2 The callee and caller properties

As we've seen, the arguments array lets us retrieve a function's arguments. The arguments object has two properties: callee, which stores a reference to the executing function, and caller, which stores a reference to the function that called the current function (or null if no function called the current function).

Normally, we know the name of the function we're calling, but if we are executing an anonymous function that was originally created with a function literal, the callee property can prove useful. Example 9-4 shows a function, created with a function literal, that performs recursive executions without knowing its own name.

Example 9-4. Counting down with callee
count = function (x) {
  trace(x);
  if (x > 1) {
    arguments.callee(x - 1);
  }
}
count(25);

Obviously we can count down without using recursive anonymous functions. We'll see a more realistic example of function recursion in Section 9.9 later in this chapter. Using arguments.callee to refer to the current function (rather than the function's actual name) alleviates the need to update our code if the function's name changes.

We can use arguments.caller to execute or identify a calling function, as described in the Language Reference.

9.8.3 Passing Parameters by Value Versus by Reference

There's one more parameter subtlety we should consider—the difference between passing data to a function by value and by reference.

When we pass a primitive data value as an argument to a function, the function receives a copy of the data, not the original. Changes made to a parameter in the function have no effect on the original argument outside that function. In Example 9-5, variableName's value is initially set to 25. Changing its value to 10 within the setValue( ) function has no effect on y's value.

Example 9-5. Primitive data is passed by value
var y = 25;
function setValue (variableName) {
  variableName = 10;
}
setValue(y);
trace("y is " + y);  // Displays: "y is 25"

Primitive data is therefore said to be passed by value. When we pass composite data as an argument to a function, however, the function receives a reference that points to the same data as the original argument, not just a duplicate of the data. Altering the data via the parameter variable affects the original data and therefore affects other variables that point to the same data, even outside of the function. Composite data is therefore said to be passed by reference.

In Example 9-6, changes to the myArray parameter variable affect the external boys array because they both point to the same data in memory.

Example 9-6. Modifying composite data arguments passed by reference
// Create an array
var boys = ["Andrew", "Graham", "Derek"];

// setValue( ) sets the value of the first element of an array
function setValue (myArray) {
  myArray[0] = "Sid";        // Set the first element of the array
}

// Pass our array to the function
setValue(boys);

// Check the value of our array elements
trace("Boys: " + boys);  // Displays: "Boys: Sid,Graham,Derek"

Note that new values assigned to individual elements of the array from inside a function are reflected outside the function as well. However, suppose that instead of assigning new values to one or more elements, we assign a new value to the parameter itself. Doing so will break its association with the original argument. Subsequent changes to the parameter variable will have no effect on the original argument, as shown in Example 9-7. In this example, although the boys array is passed as an argument, the myArray parameter variable is immediately set to girls. Subsequent changes to myArray affect the girls array, not the boys array.

Example 9-7. Breaking the association between an argument and a parameter
// Create two arrays
var boys  = ["Andrew", "Graham",  "Derek"];
var girls = ["Alisa",  "Gillian", "Daniella"];

// setValue( ) ignores the passed array and modifies the girls array
function setValue (myArray) {
  myArray = girls;      // Make myArray point to girls, not boys

  myArray[0] = "Mary";  // Changes the first element of girls
}

// Pass the boys array to the setValue( ) function
setValue(boys);
trace("Boys: " + boys);   // Displays: "Boys: Andrew,Graham,Derek"
trace("Girls: " + girls); // Displays: "Girls: Mary,Gillian,Daniella"

More information on primitive and composite data can be found in Chapter 3.


Table of Contents