This section describes another advanced topic that was too esoteric for our initial discussion about function scope. Let's revisit it here now that we've learned about movie clips, function scope, and objects.
We learned in Chapter 9, "Functions" that a function's scope chain is normally determined relative to the function's declaration statement. There is, however, a subtle extension to this rule. When a function from one timeline is assigned to a variable in a different movie clip's timeline, that assignment also affects the function's scope chain. If the original function is invoked directly, its scope chain includes its original timeline, but if the function is invoked through the variable, its scope chain includes the variable's timeline.
For example, suppose we create a function called transformClip( ) that rotates and scales the current clip. We set the amount to rotate and scale the clip in the variable's rotateAmount and widthAmount:
var rotateAmount = 45; var widthAmount = 50; function transformClip ( ) { _rotation = rotateAmount; _xscale = widthAmount; } // Invoke the function transformClip( );
Next we assign transformClip to a variable, tc, in a clip called rect:
rect.tc = transformClip;
When we invoke transformClip through rect.tc, as follows, nothing happens:
rect.tc( );
Why? The function stored in tc has a scope chain that includes rect, not our original function's timeline, so rotateAmount and widthAmount are not found. But when we add rotateAmount and widthAmount variables to rect, the function can find the variables, so it works:
rect.widthAmount = 10; rect.rotateAmount = 15; rect.tc( ); // Sets rect to 10 percent width, and 15 degrees rotation
In contrast, when regular data objects on the same timeline are involved in function assignment, the assigned function's scope chain is not altered; rather, the function's scope chain is permanently determined relative to the function declaration. Example 15-4 demonstrates.
// Set our variables var rotateAmount = 45; var widthAmount = 50; // Create a transformClip() function // that prints the value of rotateAmount and widthAmount function transformClip ( ) { trace(rotateAmount); trace(widthAmount); } // Create an object that corresponds with // the rect clip in the previous example var rectObj = new Object( ); // Copy transformClip to a property of rectObj rectObj.tc = transformClip; // Set rotateAmount and widthAmount properties on rectObj rectObj.rotateAmount = 15; rectObj.widthAmount = 10; // Now invoke rectObj.tc rectObj.tc( ); // Displays 45 and 50, not 15 and 10. The scope of // rectObj.tc is the same as transformClip().
When assigned to an object property, a function is scoped to the timeline that bears the function declaration. However, when assigned to a remote movie clip, a function is scoped to the timeline of the remote clip.
Note that this behavior is actually a departure from JavaScript, in which functions are permanently scoped to objects based on the function declaration. For example, if we assume the frames of an HTML frameset to be roughly analogous to the clips in a Flash movie, then we can see the discrepancy; in JavaScript, a function assigned to a remote frame is still scoped to the frame with the function declaration, not the remote frame, as shown in Example 15-5.
// CODE ON FRAME 0 OF A FRAMESET // Assign a variable in frame 0 var myVar = "frame 0"; // Set a function in frame 1 of the frameset, and copy that // function back to frame 0 parent.frames[1].myMeth = function ( ) { alert(myVar); }; myMeth = parent.frames[1].myMeth; // Invoke myMeth() from frame 0 myMeth( ); // displays "frame 0" // CODE ON A BUTTON IN FRAME 1 OF THE SAME FRAMESET <FORM> <INPUT type="button" value="click me" onClick="myMeth( );"> </FORM> // Now click the button to invoke myMeth( ) from frame 1. // "frame 0" is displayed. // myMeth( ) is not scoped to frame 1, but to frame 0, where // the declaration statement occurred.
Copyright © 2002 O'Reilly & Associates. All rights reserved.