イベントリスナを関数内のローカル変数として作成することは多々ある。例えば、以下のようなコードだ。このコードは、ファイルパスを与えて、対象のファイルをロードする関数である。ロードの実行には、メモリ上に確保された 1 つのローダを使い回している。
function loadSomething(path:String):Void { var listener:Object = new Object(); listener.onLoad = function(event:Object):Void { trace("loaded"); }; this.fooLoader.addEventListener("onLoad", listener); this.fooLoader.load(path); }
このイディオムは手軽で強力なのだが、リスナをイベントソースから削除していないので痛い目を見る。上記の loadSomething() を n 回実行した場合、trace の総数は n ではなく、等差数列 (a1+an)n/2 に従って増加してゆく。
では、ローカル変数として定義したリスナを削除するにはどうすればよいか。コードを下記のように変更すればよい。
function loadSomething(path:String):Void { var listener:Object = new Object(); listener.onLoad = function(event:Object):Void { event.target.removeEventListener(event.type, this); trace("loaded"); }; this.fooLoader.addEventListener("onLoad", listener); this.fooLoader.load(path); }
event.target は fooLoader を意味し、event.type は onLoad に等しい。つまり、イベント発生時にリスナが破棄されることになる。
ロードイベントのような一過性のイベントでは、ローダ自体もローカル変数として定義する方法がある。しかし、ロードを中断させる際などに、ローダへのアクセスが困難となるデメリットもある。