AS2.0 でイベントを書いてみる

EventDispatcher の原理

カスタムイベントの原理は、イベントの発行元が登録者用の配列を保持し、通知を望むオブジェクトが自身をそこへ push し、発行元が発行時、配列内の登録者たちのイベントハンドラメソッドを実行するというものです。ここではその原理のみを表す簡単な例を見てみましょう。

// 新規 .fla のフレーム1
var myDispatcher: Object = new Object();
myDispatcher.addEventListener = function (eventType:String, obj:Object): Void {
  if (this[eventType] == undefined) {
    this[eventType] = new Array();
  }
  this[evntType].push(obj);
}

myDispatcher.dispatchEvent = function (eventObj:Object) {
  eventObj.target = this;
  var type:String = eventObj.type;
  var list:Array = this[type];
  var len:Number = list.length;
  for (var i:Number = 0; i < len; i++) {
  list[i][type](eventObj);
  }
}

myDispatcher.toString = function () {
  return "myDispatcher";
}

var listener1:Object = new Object();
listener1.change = function (eventObj) {
  trace("listener1がイベントの発生を通知され、\n" + "イベントハンドラメソッド [change] が実行されました。");
  trace("イベントの発生元: " + eventObj.target);
  trace("イベント名: " + eventObj.type);
}

myDispatcher.addEventListener("change". listener1);
myDispatcher.dispatchEvent({type:"change"});


出力

listener1がイベントの発生を通知され、
イベントハンドラメソッド [change] が実行されました。
イベントの発生元: myDsipatcher
イベント名: change

2行目で定義されている myDispatcher がイベントの発行元ですが、ここでは、機能を削ぎ落とし、リスナーの登録とイベントの発行のみ可能な、簡略化した例になっています。なお、ここではクラスを用いていませんが、通常はクラスファイルに書かれることになります。そしてその発行元自信がグルーバルイベントを感知する必要がある場合には、その能力を備える MovieCrip クラスを継承したクラスとして定義されることになります。その場合、32行目のようなイベント発行は、myDispatcher.onRelease などのイベントハンドラメソッド定義内に書かれ、onRelease が呼ばれたときに自身がカスタムイベントを発行するといったことがよく行われす。

3行目の myDsipatcher.addEventListener 定義内では this[eventType] という配列を定義します。ここでは、30行目の addEventListener によって eventType には "change" という文字列が代入され、myDispatcher["change"]、つまり myDispacher.change という配列が定義されます。このようにイベント名そのものを配列名にすることによって、複数のイベントの定義を可能にしています。各イベントにそれぞれ専用のリスナー登録用配列が設けられるわけです。尚、my.events.EventDispatcher では、わずかな可能性ではありますが、名前衝突を回避するため、配列名は"__q_" + eventType になっています。

23行目で出てくる listener1 がここでのリスナーになります。ここでは [change] というイベントハンドラメソッドを24〜29行目で定義し、30行目の addEventListener で myDispatcher に対して [change] というイベントを通知されるように登録しています。

32行目で myDispatcher オブジェクトは change イベントを発行していますが、その際、 [type: "change"] という Object リテラルを引数として渡しています。これはイベント発行元のオブジェクト自身で、これも必要ならば、リスナーのイベントハンドラメソッドの値を調べたい場合などに便利です。尚、リスナーのイベントハンドラメソッド内では、 [this] はそのリスナー自身を指します。