読者です 読者をやめる 読者になる 読者になる

kkAyatakaのメモ帳。

誰かの役に立つかもしれない備忘録。

addEventListenerの登録処理

addEventListenerの登録処理ではまったので、改めて調べてみた。

同じ関数

2重に登録されない。

addEventListener(FlexEvent.CREATION_COMPLETE, createComp1);
addEventListener(FlexEvent.CREATION_COMPLETE, createComp1);

これはcreateComp1の処理が1回だけ呼ばれる。

useCapture引数が異なる

改めてドキュメントを読んでいたら、これは違うものとして登録されるとの事。

addEventListener(FlexEvent.CREATION_COMPLETE, createComp2, true); 
addEventListener(FlexEvent.CREATION_COMPLETE, createComp2, false); 

実際に同じ関数、引数違いで行ったところ2回呼ばれた。まあ、呼ばれるタイミングが異なるので、関数が同じでも2回呼ばれるのは当然の動作。

無名関数

ちゃんと認識してなかったのはコレ。

private function initWnd():void {
  addEventListener(
    FlexEvent.CREATION_COMPLETE,
    function(e:FlexEvent):void {
      trace("creationComplete nameless");
    }
    );
}

無名関数(というか関数内関数)はその呼び出し毎の都度生成のようで、関数呼び出し毎に別の関数が登録される事になる。ここで、initWndを2回呼び出すと結果として登録した処理も2回実行される。

実際に初期化処理を2回呼び出す事は無いと思うが、場面が変われば状況は違ってくる。何となくfunctionはグローバルな所に存在するイメージを持っていたみたいで、バグとして発生していた現象がすぐに理解できなかった。そういえば、無名関数と弱参照でイベント登録をして、うまく処理されないなぁといった事があったが、登録した無名関数がGCに回収されてたって事ね...

検証コード

実際に動作を確認したソース。無名関数の動作で明らかだけど、createComp1、createComp2の登録動作で、関数が異なる場合の動作も確認できる。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
  xmlns:mx="http://www.adobe.com/2006/mxml"
  width="400" height="300"
  initialize="init(event)">

  <mx:Script>
  <![CDATA[
    import mx.events.FlexEvent;

    private function init(e:FlexEvent):void {
      // 同じ設定の場合1回しか登録されない
      addEventListener(FlexEvent.CREATION_COMPLETE, createComp1);
      addEventListener(FlexEvent.CREATION_COMPLETE, createComp1);

      // useCapture引数が違う場合、別々に登録される
      addEventListener(FlexEvent.CREATION_COMPLETE, createComp2, true); 
      addEventListener(FlexEvent.CREATION_COMPLETE, createComp2, false); 

      // 無名関数で登録した場合、関数のオブジェクトが異なるので、
      // 別々に登録される
      initWnd();
      initWnd();
    }

    private function createComp1(e:FlexEvent):void {
      trace("creationComplete 1")    
    }

    private function createComp2(e:FlexEvent):void {
      trace("creationComplete 2", "phase : " + e.eventPhase);
    }

    private function initWnd():void {
      addEventListener(
        FlexEvent.CREATION_COMPLETE,
        function(e:FlexEvent):void {
          trace("creationComplete nameless");
        }
        );
    }
  ]]>
  </mx:Script>

</mx:WindowedApplication>

実行結果。createComp1は1回、createComp2はタイミング違いで2回、無名関数は2回呼ばれている事が分かる。

creationComplete 2 phase : 1
creationComplete 1
creationComplete 2 phase : 2
creationComplete nameless
creationComplete nameless