Macromedia Flash非公式テクニカルノート forループでMovieClipに設定したイベントハンドラメソッドから変数を参照する
Platform: All forステートメントを使って、複数のインスタンスをまとめて処理する場合の問題です。そのループ処理中で、MovieClipインスタンスにイベントハンドラメソッドを設定するとき、メソッドに設定した(コールバック)関数内からforステートメントのカウンタ変数を参照すると、意図した結果にならないことがあります。 タイムライン上でMovieClipに対してイベントハンドラメソッドを設定する場合には、メソッドの(コールバック)関数内では、this参照とthisなしの「デフォルト参照」が異なります。this参照とデフォルト参照との違いについて、まだ理解が十分でないという方は、先に「Buttonのthis」をお読みください。 1. forステートメントで複数のMovieClipにイベントハンドラメソッドを定義する イベントハンドラメソッドに設定した(コールバック)関数には、テスト用のtrace()ステートメントがあるだけです。インスタンス自身のターゲットパスthisと、配列からエレメントをひとつ取出して出力します。配列から取出すエレメントのインデックスには、forステートメントで使用したカウンタ変数iを指定しています。 スクリプト001■複数のMovieClipにイベントハンドラメソッドを定義
MovieClip.onMouseDownイベントは、ステージのどこをクリックしても発生します。したがって、ステージ上をクリックすれば、生成した3つのMovieClipインスタンスすべてのMovieClip.onMouseDownイベントハンドラメソッドが呼出されます。そのとき、[出力]結果はどうなると予想しますか? [出力]パネルには、つぎのように表示されます(図001)。ひとつめのターゲットパスは正しく出力されるものの、ふたつめの配列エレメントがすべてundefinedになっています。これは、なぜでしょう? 図001■スクリプト001の[出力]パネルの表示
2. forステートメントのカウンタ変数はどこに設定されるか
[出力]を見るとつぎのように、タイムライン上とイベントハンドラメソッドの関数内のいずれも、カウンタ変数iの値が3になっています(図002)。つまり、3つのインスタンスすべてのイベントハンドラメソッドが、同じタイムライン上のカウンタ変数iを参照しているということです。 図002■スクリプト002の[出力]パネルの表示
(1) 生成した3つのMovieClipには、それぞれ配列から順に取出したインスタンス名が設定され、それらすべてにMovieClip.onMouseDownイベントハンドラメソッドが正しく定義されています。つまり、この処理についてだけみれば、カウンタ変数iがそれぞれ0、1、2と別個に認識されたということです。 (2) しかし、イベントハンドラメソッドの(コールバック)関数内から参照したカウンタ変数iは、すべて同じ値3になってしまっています。forステートメントはカウンタ変数iが2になるまではループ内の処理を行い、3にカウントアップされると継続条件を外れてループ処理を終了します。つまり、3というのは、ループ処理を終えたカウンタ変数iの値です。 この(1)と(2)の処理結果の違いを、正しく理解する必要があります。 (1)のインスタンス名の設定は、forループの1回の処理でそれぞれ完結します。配列からインデックスiのエレメントを取出し、新たに生成したMovieClipのインスタンス名として設定します。取出されたエレメントの文字列は、インスタンス名として設定されたときには、すでに変数iを参照していません[*1]。 イベントハンドラメソッドも1回の処理でMovieClipへの設定は済み、つぎのループでカウンタ変数の値が変わったからといって、設定済みのターゲットインスタンスがその値に連動して変更されることはありません。 ところが、(2)のイベントハンドラメソッド内のカウンタ変数iは、状況が異なります。変数iは、MovieClip.onMouseDownイベントが発生したとき、(コールバック)関数が呼出されて値が参照されます。このとき変数iにはターゲットがありませんので、デフォルト参照であるスクリプトの記述されたタイムライン上の値を探します。 タイムライン上には、forループの処理を終えたカウンタ変数iが値3をもっています。したがって、どのMovieClipインスタンスも、スクリプトの記述場所にあるタイムライン変数iを、共通に参照する結果となったのです。
3. イベントハンドラメソッドからMovieClipごとに異なる値を参照させる スクリプトの記述場所のタイムライン変数iは値が変化しますし、インスタンスにかかわらず共通の参照になってしまいます。したがって、インスタンスごとの値として、MovieClipに個別に設定する必要があるのです。 つぎのスクリプトは、各ループ処理中にカウンタ変数iの値を、MovieClipに同名のタイムライン変数iとして設定します(スクリプト003)[*2]。そうすれば、カウンタ変数の値が変わっても、個々のMovieClipに設定された(タイムライン)変数の値はそのまま保持されます。 スクリプト003■MovieClipに値を設定してイベントハンドラ内から参照
MovieClip.onMouseDownイベントハンドラメソッドを定義する直前に、MovieClipインスタンス(ローカル変数_mcに格納)に変数iを設定し、forステートメントのカウンタ変数iの値を代入しています。これで、カウンタ変数iの値がつぎのループで変わっても、インスタンスに設定された(タイムライン)変数iはそのまま保持されます。 MovieClipに定義したイベントハンドラメソッドの(コールバック)関数内から、インスタンスに設定されたタイムライン変数を参照するには、thisが必要になります。thisをつけないデフォルト参照は、スクリプトを記述したタイムラインになってしまうからです。 ステージをクリックすると、[出力]パネルには以下のように表示されます(図003)。this.iは各MovieClipインスタンスに設定されたタイムライン変数を参照するので、それぞれ異なった値になっています。 図003■スクリプト003の[出力]パネルの表示
_____ 作成者: 野中文雄 Copyright © 2001-2006 Fumio Nonaka. All rights reserved. |
|||||||||||