Adobe Flash非公式テクニカルノート 関数・メソッドとthis
オブジェクトに設定した関数やメソッド内におけるthis参照は、ActionScript 3.0では2.0とは仕様が変わりました。本稿はその違いについて、簡単に説明します。 1. フレームアクションに定義した関数内のthis イベントハンドラメソッドはActionScript 3.0にはありませんので、比較ができるように2.0で以下のようなフレームアクションを書いてみます(スクリプト001)。タイムラインにはMovieClipインスタンスmy_mcを配置しておきます。また、[パブリッシュ設定]で、[ActionScriptのバージョン]は[ActionScript 2.0]を選びます。 スクリプト001■関数をMovieClipインスタンスに設定して呼出し結果を比較 ー ActionScript 2.0
関数xTest()を直接呼出すと、thisがあってもなくてもスクリプトを記述したタイムラインが参照され、フレームアクションに宣言したタイムライン変数name_strの値"main"が[出力]されます。 ところが、関数xTest()をMovieClipインスタンスmy_mcに設定して、その関数を呼出すと、this参照のあるなしで値の[出力]される変数が変わります。thisは関数の設定されたインスタンスmy_mcを参照するので、my_mcに設定した変数name_strの値"my_mc"が[出力]されます。ところが、thisを指定しないとスクリプトを記述したタイムラインが参照され、タイムライン変数として宣言したname_strの値"main"が取出されるのです。 同じ内容のスクリプトを、ActionScript 3.0で試してみましょう(スクリプト002)。ActionScript 2.0(スクリプト001)との違いは、関数の戻り値の型指定を頭文字が小文字のvoidに変えただけです。 スクリプト002■関数をMovieClipインスタンスに設定して呼出し結果を比較 ー ActionScript 3.0
ActionScript 3.0では、thisがあってもなくても、また関数xTest()を直接実行しても、MovieClipインスタンスmy_mcに設定して呼出しても、[出力]されるのはつねにフレームアクションにタイムライン変数として宣言されたname_strの値"main"になります(図001)。これは関数内のスコープ(参照される範囲)[*1]がthisのあるなしに拘らず関数の定義されたインスタンスになり、関数が他のオブジェクトに設定されてもスコープは変わらないからです。 図001■ActionScript 3.0では関数内のスコープが変わらない
2. クラスに定義したメソッド内のthis ActionScript 2.0にはこのためにDelegateクラスが備わり()、メソッドのthis参照先を変えることができます。以下のテスト用クラスScopeTest(スクリプト003)は、コンストラクタに引数としてMovieClipインスタンスを渡すと、MovieClip.onEnterFrameイベントハンドラメソッドが設定されて、インスタンスを回転させます。クラスScopeTestのコンストラクタは、たとえばフレームアクションからタイムラインに配置したMovieClipインスタンスmy_mcを引数にして、つぎのように呼出します。 // フレームアクションスクリプト003■MovieClipインスタンスに回転のアニメーションを設定するクラス ー ActionScript 2.0
コンストラクタに渡された引数のMovieClipインスタンスに対してMovieClip.onEnterFrameイベントハンドラメソッドを設定するとき、コールバック関数にDelegate.create()メソッドを適用してthis参照をクラスインスタンスに変更していることにご注目ください。this参照を変えないと、コールバック関数rotate()内の参照にはthisが補われて、メソッド内のステートメントはつぎの記述と同じになってしまいます。 this.target_mc._rotation += 10; ActionScript 2.0では、イベントハンドラメソッドに設定したコールバック関数内のthisは、メソッドの設定されたインスタンスを参照します。つまり、前掲クラスScopeTest(スクリプト003)のrotate()メソッド内のthisは、MovieClipインスタンスtarget_mcになり、上記ステートメントはtarget_mc内の識別子target_mcを探してしまうことになります。 この問題を解決するために、Delegate.create()メソッドにより、rotate()メソッド内のthisがScopeTestインスタンスを参照するよう変更し、正しくMovieClipインスタンスtarget_mcをコントロールできるようにする必要があるのです。 それに対して、ActionScript 3.0では、メソッド内のthisはつねにそれが定義されているインスタンスを参照します(this参照を省略した場合も、2.0と同じくthisが補われたものとして扱われます)[*2]。したがって、とくに参照を変更するという操作は必要ありません。 前掲ActionScript 2.0によるスクリプト003と同じ内容を、3.0で定義したクラスScopeTestはつぎのようになります(スクリプト004)。 スクリプト004■MovieClipインスタンスに回転のアニメーションを設定するクラス ー ActionScript 3.0
DisplayObject.enterFrameイベントにリスナー関数rotateを登録する際も、rotate()メソッド内も、とくに参照を変更することなく、ScopeTestインスタンスのプロパティtarget_mcを参照することができています。つぎのフレームアクションを記述して[ムービープレビュー]を確かめれば、タイムラインに配置したインスタンスmy_mcに回転のアニメーションが設定されます(図002)。 // フレームアクション図002■コンストラクタに渡されたインスタンスに対して回転のアニメーションを設定
3. 名前のない関数内のthis
図003■名前のない関数内では設定されたオブジェクトがthisとして参照される
なお、ActionScript 3.0にも2.0と同じく、this参照を変更するFunction.apply()やFunction.call()メソッドが備わっています。しかし、タイムラインやクラスに定義した関数・メソッドのthis参照は、これらのメソッドを用いても変えることはできません。Function.apply()やFunction.call()メソッドは、名前のない関数についてのみ適用することが可能です。 スクリプト006■名前のない関数に対してFunction.apply()メソッドを呼出す ー ActionScript 3.0
作成者: 野中文雄 Copyright © 2001-2008 Fumio Nonaka. All rights reserved. |
||||||||||||||||