Function.apply( ) Method | Flash 6 |
invoke a function as an object method, passing parameters in an array |
The object on which theFunction is called as a method.
An array of values passed as arguments to theFunction.
The return value of theFunction.
The apply( ) method invokes theFunction as a method of thisObj and passes the values of parametersArray to theFunction as arguments. Within theFunction, the value of the this keyword is a reference to thisObj. The return value of apply( ) is simply the return value of theFunction. To invoke theFunction without specifying an object reference, use null as the value of thisObj. To pass a comma-delimited list of arguments to theFunction, instead of passing the values in a parametersArray, use Function.call( ).
The apply( ) method is normally used to alter the value of the this keyword when running a function, or to supply an array of arguments to a function in place of a comma-delimited list.
The following code shows the basic syntax of apply( ):
// Create a function function square (x) { return x*x; } // Invoke the function as a method of _root, passing an array literal // containing the single argument value 10. tenSquared = square.apply(_root, [10]);
This example has little practical purpose�it would be easier to invoke the function directly, as in: _root.square(10);. The apply( ) method becomes more useful when we need to dynamically specify the object on which to invoke a method, for example, when we want to use one method with many different objects that do not share a common class or superclass. Suppose we have getWidth( ) and moveClipTo( ) methods that we want to use with both a rectangle and a circle object. Here's the code we can use to create a generic method, Rectangle.invokeAsMethod( ), that invokes getWidth( ), moveClipTo( ), or any other function as a method of a rectangle object:
// A Rect class function Rect (width, height, x, y) { this.width = width; this.height = height; this.x = x; this.y = y; } // Method to invoke any passed func as a method of a Rect object. // Note that func is a function reference, not a string. Rect.prototype.invokeAsMethod = function (func) { // Invoke func as a method of this Rect, passing along any // arguments that were supplied. func.apply(this, arguments.slice(1)); }; // A simple generic getWidth function that takes no arguments function getWidth () { trace("width: " + this.width); return this.width; } // A slightly more complex example, moveClipTo, that takes arguments function moveClipTo (newX, newY) { this.x = newX; this.y = newY; } // Make a new Rect object box = new Rect(15, 20); // Invoke getWidth on box box.invokeAsMethod(getWidth); // Displays: width: 15 // Invoke moveClipTo on box, passing the newX and newY arguments box.invokeAsMethod(moveClipTo, 100, 200); // Check if it worked... trace("box x: " + box.x); // Displays: box x: 100 trace("box y: " + box.y); // Displays: box y: 200
This practice is not necessarily recommended when the objects can logically be assigned a common class or superclass. For example, rather than use apply( ) in our rectangle example, it's more appropriate to create a Shape superclass that defines moveClipTo( ) and getWidth( ) methods inherited by both Rect and Circle. For a more legitimate application of the apply( ) method, see the CountDown class shown in the following Example.
The following class, CountDown, invokes a specified object's method after a delay. It uses apply( ) to ensure that the method executes on the correct object and to pass the method arguments as a convenient array.
/* * CountDown Class * Desc: Calls a method after delay milliseconds. * Params: obj An object whose method will be called. * meth The string method name to call. * delay The time (milliseconds) to wait before calling. * arg4...argn The arguments to pass to meth. */ function CountDown (obj, meth, delay) { // Remember how long to wait before calling meth. this.delay = delay; // Store a reference to the method. this.callback = obj[meth]; // Store a reference to the object. this.obj = obj; // Store extra arguments. We'll pass them to meth later. this.args = arguments.slice(3); // Set an empty intervalID. Used with setInterval(). this.intervalID = -1; // Start the countdown this.start(); } /* * Method: start() */ CountDown.prototype.start = function () { // Invoke the method-caller after this.delay milliseconds. this.intervalID = setInterval(this, "invokeCallback", this.delay); }; /* * Method: stop() */ CountDown.prototype.stop = function () { // Stop the interval so that it doesn't call the method again. clearInterval(this.intervalID); this.intervalID = -1; }; /* * Method: invokeCallback() */ CountDown.prototype.invokeCallback = function () { // Time's up! Stop the countdown. this.stop(); // Invoke the callback as a method of this.obj, and pass // along this.args to use as method arguments. this.callback.apply(this.obj, this.args); }; // SAMPLE USE // Create the countdown. Will invoke // _root.output("hello", "world") after 1000 milliseconds. count = new CountDown(_root, "output", 1000, "hello", "world"); // The method to invoke function output (arg1, arg2) { trace("output: " + arg1 + ", " + arg2); }
Function.call( ), the Arguments object; Chapter 12