変数のvar宣言と関数のfunction定義は、スクリプトが実行される前に初期化されます。つまり、var宣言した変数とfunction定義した関数は、スクリプトのステートメントが処理される前に、予めメモリに読込まれるということです。
1. スクリプトペイン内の場合
ひとつのスクリプトペイン(ウィンドウ)の中では、変数のvar宣言や関数のfunction定義が後に記述されていたとしても、それらより前のステートメントで変数にアクセスしたり、関数を呼出すことができます。たとえば、つぎのようなテスト用のフレームアクションを試してみます(スクリプト001)。
スクリプト001■後に定義された関数を呼出してその後に宣言された変数値を[出力]
// フレームアクション
xTest();
function xTest() {
trace(i);
}
var i:int;
|
最初のステートメントで、後にfunction定義した関数xTest()を呼出しています。そして、その関数内では、さらに後のステートメントでvar宣言されている変数iの値を、trace()関数により[出力]しています。その結果、[出力]パネルには0が表示されました(図001)。
図001■後に定義した関数を呼出してさらにその後で宣言した変数値を[出力]
int型データのデフォルト値である0が[出力]される。
|
第1に、[出力]パネルに値が表示されたのは、関数xTest()が呼出されたことを示します。第2に、出力された値0は、int型で宣言された変数の初期値です。したがって、変数宣言もすでに有効であることがわかります[*1]。
[*1] 変数のvar宣言がスクリプトのステートメントの処理に先立って初期化されるとしても、その変数への値の代入は通常のステートメントとして、記述された順に処理されます。たとえば、前記スクリプト001をつぎのように修正してみます(スクリプト002)。
スクリプト002■変数に値が代入される前後で変数値を確認
// フレームアクション
xTest();
function xTest() {
trace(i);
}
var i:int = 1;
xTest();
|
スクリプト001と異なり、変数iをint型で宣言すると同時に、整数1を代入しています。最初のステートメントで関数xTest()を呼出すと、int型のデフォルト値である0が[出力]されます(図002)。つまり、int型変数として初期化はされていても、値がまだ代入されていないということです。
変数のvar宣言と代入を行ったステートメントの後に関数xTest()を呼出すと、ようやく代入された値1が[出力]されます(図002)。つまり、代入の処理は通常のステートメントとして、記述された順序で実行されていることを意味します。
図002■変数に値が代入される前後で変数値が異なる
変数への値代入前と後とで、関数呼出しの結果が異なる。
|
以上から、変数をvar宣言すると同時に値を代入した場合、型指定を含めた変数の宣言とその変数への値の代入とは、内部的に分離されていることがわかります。スクリプトの実行に先立って初期化されるのは変数の宣言であって、代入式は通常のステートメントと同じく、その記述した順番で処理されます。
|
2. 同じタイムラインの別フレームの場合
同じタイムライン上で、後のフレームにvar宣言されている変数やfunction定義されている関数も、前のフレームからアクセスすることができます。たとえば、先のテスト用フレームアクション(スクリプト001)を、(1)関数を呼出す最初のステートメントと(2)関数xTest()の定義、および(3)変数iの宣言とに分け、この順でそれぞれ第1、第2、第3フレームに設定してみます(図002)。
図003■関数の呼出しとその定義および変数宣言をその順でフレームに分割
後のフレームに定義した関数や宣言した変数も、前のフレームからアクセスできる(図の3つの[アクション]パネルは画像で合成した)。
|
[出力]パネルには、やはり0が表示されます。したがって、後のフレームで定義されている関数を呼出し、さらにその後のフレームに宣言されている変数にアクセスできることがわかります。
3. 入れ子になったタイムラインの場合
入れ子になったタイムライン(MovieClip)のフレームアクションは、親から子の順に処理されます。しかし、変数および関数の初期化は、これらに先立って行われます。つまり、子のフレームアクションでvar宣言された変数やfunction定義された関数も、親のフレームアクションからアクセスすることができます。
テストとしてスクリプト001と同一の処理内容を、今度は階層化されたインスタンスに分けて設定してみました(スクリプト003)。まず、メインタイムラインから、そこに配置した子のMovieClipインスタンスparent_mcに定義された関数xTest()を呼出します。そして、関数xTest()で[出力]する変数iは、さらに入れ子にした孫のインスタンスchild_mcのフレームアクションで宣言しています(図004)。
スクリプト003■メインタイムラインから子の関数を呼出し孫に変数宣言
// メインタイムライン
// フレームアクション
parent_mc.xTest();
|
// MovieClip: parent_mc
// フレームアクション
function xTest() {
trace(child_mc.i);
}
|
// MovieClip: child_mc
// フレームアクション
var i:int;
|
図004■階層化された子に関数定義しさらに孫で変数宣言
[ムービープレビュー]を試すと、やはりint型変数のデフォルト値0が[出力]パネルに表示されます[*2]。
[*2] さらに、メインタイムラインのフレームアクションでなく、[ドキュメントクラス](図004)のコンストラクタから関数を呼出し、変数にアクセスすることも可能です(スクリプト004)。[ムービープレビュー]を試すと、前述のスクリプト003と同じく、[出力]パネルには0が表示されます。
図005■[プロパティ]インスペクタで[ドキュメントクラス]を設定
スクリプト004■ドキュメントクラスからMovieClipの関数を呼出して入れ子のインスタンスの変数にアクセス
// ActionScript 3.0クラス定義ファイル: Test.as
// [ドキュメントクラス]に設定
package {
import flash.display.MovieClip;
public class Test extends MovieClip {
function Test() {
parent_mc.xTest();
}
}
}
|
なお、[パブリッシュ設定]の[ActionScript 3.0設定]で、[ステージのインスタンスを自動宣言]はオンが選択されています。
|
4. 変数宣言と関数定義はどこに記述すべきか
以上より、Flashムービーファイルのフレームアクションでvar宣言された変数やfunction定義された関数は、すべてのステートメントに先立って初期化されることがわかりました。つまり、変数宣言や関数定義は、どこに記述しても、任意のフレームアクションからアクセスすることができるということです。
しかしもちろん、どこにでも書けるということと、そうすることがよいかどうかは別の問題です。スクリプトは可能なかぎりまとめた方が、わかりやすいですし、管理もしやすいでしょう。基本的には、タイムラインの第1フレームアクションにまとめて記述することをお勧めします。
作成者: 野中文雄
作成日: 2007年10月29日