図2●「アプリケーション」を指定したうえで,1フレーム目を選択して[アクション]パネルでタイムライン変数を宣言しているところ
図2●「アプリケーション」を指定したうえで,1フレーム目を選択して[アクション]パネルでタイムライン変数を宣言しているところ
[画像のクリックで拡大表示]
リスト2●「フォーム1」にタイムライン変数userNameを宣言・定義し,ボタンのイベント・ハンドラで値を取得/設定するコード
リスト2●「フォーム1」にタイムライン変数userNameを宣言・定義し,ボタンのイベント・ハンドラで値を取得/設定するコード
[画像のクリックで拡大表示]
図3●リスト2のコードの実行結果
図3●リスト2のコードの実行結果
[画像のクリックで拡大表示]
リスト3●スコープチェーンによる変数の値の取得をチェックするコード
リスト3●スコープチェーンによる変数の値の取得をチェックするコード
[画像のクリックで拡大表示]

 タイムライン変数は,「フォームアプリケーション」や「スライドプレゼンテーション」でコンポーネントを使用してアプリケーションを作成する場合に,個々のフォーム,スライド,コンポーネントごとに保有される変数です*8。オブジェクト指向プログラミングをご存じの方は,任意のフォームやスライドのインスタンスに,後付けでプロパティ(フィールド)を追加して,そこに値を格納できる仕組み,というイメージで考えてみてもよいでしょう。

 タイムライン変数は,タイムラインの任意のフレーム上でvarステートメントを使用して宣言します。「フォームアプリケーション」や「スライドプレゼンテーション」を開発しているときには[タイムライン]パネルは通常隠されています。タイムライン変数を宣言する場合には[タイムライン]パネルを開いて,[スクリーンアウトラインペイン]で「アプリケーション」あるいは「フレーム1」を指定したうえで1フレーム目を選択して[アクション]パネルを開き,varステートメントを使って記述します(図2[拡大表示])。

 例えば,「フォームアプリケーション」の「フォーム1」にタイムライン変数を宣言し,「フォーム1」上に配置したボタンからその内容を取得/設定するには(リスト2[拡大表示])のようにコードを記述します。「this._parent」は,ボタンから「フォーム1」を指定するターゲットパスです。したがって「this._parent.userName」は「フォーム1.userName」と同じ意味になり,「フォーム1」のプロパティを扱うのと同じ構文で,タイムライン変数userNameの値を取得/設定できます*9。Flashのメニューで[制御]-[ムービープレビュー]と選んでプログラムを実行し,ボタンを押すと図3[拡大表示]のウィンドウが現れます。

 最後は,グローバル変数です。ActionScriptには,プログラムのどこからでも「_global」という識別子で参照できる「_globalオブジェクト」が用意されています。グローバル変数は,この_globalオブジェクトに作成する変数です。タイムライン変数と同じように,_globalオブジェクトに後付けで追加できるプロパティととらえてもよいでしょう。

 _global変数は,_global識別子を指定して直接_globalオブジェクトに追加します。varステートメントは使用しません。例えば,defaultSpeedというグローバル変数を定義して10という値を代入するには「フォーム1」のloadイベント・ハンドラに次のように記述します。

_global.defaultSpeed = 10;

ボタンを押してその値を表示させるには

trace(_global.defaultSpeed);

とボタンのclickイベント・ハンドラに記述します。

 グローバル変数は,プログラムのどこからでも参照できるため,ややこしいターゲットパスを使わないですむという利点があります。しかし,オブジェクト指向の情報隠ぺいの概念から考えると,あまり多用すべきでは無いでしょう。このあたりは,開発者がルールを決めて,それに従って変数を使い分ける必要があるでしょう。

スコープチェーンという概念

 ActionScriptで変数を使用する場合,「スコープチェーン」というFlash特有の概念に注意する必要があります。スコープチェーンは,解決できない名前(変数名)*10がある場合に,その名前があるかどうかを一定の順番で検索していき,最初に見つけた値を返すという仕組みです。具体的には,最初にローカル変数を探し,無ければタイムライン変数を探し*11,最後にグローバル変数を探す,という順番になります。

 例えば,[フォームアプリケーション]で「フォーム1」フォームにリスト3[拡大表示]のようなコードを記述して実行してみましょう。「ume」と表示されます。変数userNameはrevealイベント内で宣言されていないのに,どのようにして取得しているのでしょうか。ここで登場するのがスコープチェーンです。

 まず,revealイベント・ハンドラ内で「userName」という名前の変数を探します。しかし,どこにも宣言されていません。そこで今度は,タイムライン変数に「userName」という変数があるかどうかを探します。すると,タイムラインで宣言した変数が見つかります。この時点でタイムライン変数の値である「ume」を表示するというわけです。

 もしタイムライン変数にも探している変数名(userName)が見つからない場合には,その外側の_glabalオブジェクト上で変数名を探します。それでも見つからなければ,はじめて「undefined」(未定義値を表す値)を変数の値として返します。ActionScriptでは変数名で大文字・小文字を区別します。そのため,ちょっとしたスペルミスでも別の変数として扱われてしまいます。そのうえ,宣言していない変数も扱える仕様となっていますので,スペルミスが原因で知らず知らずのうちに新しい変数を作成してしまった,なんて凡ミスをしないように十分に注意しましょう(カコミ記事「ローカル変数はvarで宣言した方が安全」を参照)。

☆          ☆          ☆

 今回は,Flash独特の仕組みであるムービークリップとタイムライン,それにかかわる変数とそのスコープの仕組みを説明しました。次回は,ActionScriptで自作のクラスを作成して利用する方法をご紹介しようと思います。お楽しみに。


ローカル変数はvarで宣言した方が安全


リストA●varステートメントで宣言した変数の有効範囲を調べるコード
[画像のクリックで拡大表示]

 リスト2あるいは3のコードをリストA[拡大表示]のように変更してみましょう。実行結果は「yoshioka」「ume」と表示されます。なぜこうなるのかわかりますか。

 リストAの(2)では,「userName」という変数名を探す際に,ローカル変数に同名の変数があるため,そこで名前の探索をストップし,「yoshioka」という値を表示します。続く(3)では,「this.userName」のthisが「フォーム1」を表すので,「フォーム1のuserNameプロパティの値」,すなわちタイムライン変数「userName」の値である「ume」が表示されるわけです。revealイベント・ハンドラの処理内でvarステートメントを使用して宣言される変数は,その処理内のみで有効なローカル変数ですから,タイムライン変数であるuserNameの値を上書きしない点に注目してください。

 リストAの(1)を

userName = "yoshioka";

に変更すると,スコープチェーンをたどって,タイムライン変数であるuserNameの値を「yoshioka」に書き換える処理となります。したがって,結果は「yoshioka」が二つ連続で表示されます。変数を扱う場合には,自分が扱いたい変数がローカル変数なのか,それともタイムライン変数なのかをしっかりと意識し,varステートメントをうまく使って意図通りの変数にアクセスできるようにしましょう。


つづく…

吉岡 梅(よしおか うめ)
山梨県在住のソフトウエア開発者。

◆下記のURLから,サンプル・プログラムを無償ダウンロードできます
http://software.nikkeibp.co.jp/software/download/down04c.html#200407