FC2ブログ

今日調べたことをまとめてみる

おとといの日記に書いた、「色々と調べたいこと」について今日も調べた。
なんとか結果をまとめてみた。

(1)currentTargetとsrcElementの違い
event.target と window.event.srcElement は同じ要素を指す。(window.eventはIEのみ)
event.target はイベントが発生した要素を、event.currentTarget はイベントリスナをセットした要素を指す。

リスナをセットした要素が子孫要素を持っていなければ、event.currentTarget と event.target は同じ要素を指す。
<event.currentTarget と event.targetが異なる例>
<body onload="init()">
<div id="DIV"><button id="BUTTON">click</button></div>
<body>
において、
function showevent(evt){
  var msg = "event.target.id=" + evt.target.id + "\n" +
    "event.currentTarget.id=" + evt.currentTarget.id;
  alert(msg);
}
function init(){
  var elm = document.getElementById("DIV");
  elm.addEventListener("click", showevent, false);
}
のようにして<div>にイベントリスナをセットした場合、
<button>をクリックすると
event.target.id=BUTTON
event.currentTarget.id=DIV
と表示される。

(2)クロージャとは?
参考資料:猿でもわかるクロージャ超入門 まとめ

JavaScriptでは、関数内で定義された内部関数は、外側の関数のローカル変数を参照できる。
そのような内部関数をクロージャと呼ぶ。
例)
function outer(){
  var x = 1;  // outerのスコープ内で変数を定義
  return function (){   //この関数が「クロージャ」
    alert(x);  // "関数内関数"の中で、outerスコープの変数を参照。
    x = x + 1;
  };
}

outer() が実行されるたびに、無名関数 function (){alert(x);x = x + 1;} および無名関数が参照する変数xが生成される。
この変数xは保持される。
var f1 = outer();  // function (){alert(x);x = x + 1;} のオブジェクトと変数xが生成&初期化される。x = 1
f1();  // "1"をalert後、x = x + 1 が実行される。x = 2
f1();  // "2"をalert後、x = x + 1 が実行される。x = 3
var f2 = outer();  // function (){alert(x);x = x + 1;} のオブジェクトと変数xが生成&初期化される。x = 1
f2();  // "1"をalert後、x = x + 1 が実行される。x = 2
f1();  // "3"をalert後、x = x + 1 が実行される。x = 4
f1とf2は異なるオブジェクトのため、変数xも別々に生成される。

(3)無名関数を使用する場合のメモリ消費問題
参考資料:element.addEventListener - MDC -

イベントリスナをセットする際に無名関数を使用する。
例)
var listener = function(){jsObj.init();}
window.addEventListener("load", listener, false);
この場合、jsObjだけでなく、無名関数 function(){jsObj.init();} がアクセス可能な全ての変数がメモリに保持される。
removeEventListener を呼び出すか無名関数への参照を全て削除すれば、変数の消費するメモリが解放されるようになる。

(4)無名関数使用とIE循環参照の関係
参考資料:Internet Explorer リーク パターンを理解して解決する

無名関数等でクロージャを作成し、クロージャをイベントとして要素にセットする
例)
function AttachEvents(element){
  // クロージャ作成
  var listener = function(){ClickEventHandler.call(element)}
  element.attachEvent("onclick", listener);
}
function ClickEventHandler(){
  // thisでイベント発生元要素を取得
}
function SetupLeak(){
  AttachEvents(document.getElementById("LeakedDiv"));
}
イベントセットにより、id="LeakedDiv" の要素 → クロージャ function(){ClickEventHandler.call(element)} の参照が発生。
クロージャは定義元の関数への参照を保持するので、 クロージャ → element → id="LeakedDiv" の要素
という参照も発生し、循環参照となってメモリリークが発生する。


自分が理解できる程度にはまとめられたが、分かり易いかどうか客観的に判定できない。
間違って理解しているところもあるかもしれない。
スポンサーサイト



コメント

コメントの投稿

非公開コメント

プロフィール

himax64

Author: 南西
30代後半の無職です。
就活もせずダラダラ生きてます。
作ったもの

最新記事
人気記事
検索フォーム
カテゴリ
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QRコード
カウンター