JavaScript の EventListener における this について
Firefox 3 にて検証。
あるオブジェクトに属するメソッド(関数オブジェクト)をイベントリスナーとして登録した場合、その登録の方法によってメソッド内で使用される this の意味が違ってくるよという話。
まずはこんなオブジェクトをつくってみる
// MyEventListener オブジェクト作成 var MyEventListener = function() { return this} // MyEventListener オブジェクトにonMouseClickメソッドを追加 MyEventListener.prototype = { onMouseClick: function() { alert(this); } //←ここの this が今回の主役 } // MyEventListener から myEventListener オブジェクトを作成 var myEventListener = new MyEventListener();
そして、myEventListener.onMouseClick をイベントリスナーとして登録してみる
イベントリスナーとして素直に関数名を表記した場合
アラートには "[object HTMLParagraphElement]" と表示される。
この場合、 this = イベントリスナーが登録されたターゲット 。
var div = getElementById("div"); div.addEventListener("click", myEventListener.onMouseClick, false);
イベントリスナーとして無名関数を使用した場合
アラートには "[object Object]" と表示される。
この場合、 this = イベントリスナーオブジェクト 。
var div = getElementById("div"); div.addEventListener("click", function() { myEventListener.onMouseClick() }, false);
いったん無名関数を間にはさむので this の意味が違ってくるのは当然といえば当然なんだろうけど、注意しないといろいろと面倒なことになりそうなのでメモしておきます。
(追記) Mozilla Developer Center に関連情報が書いてあった
https://developer.mozilla.org/ja/DOM/element.addEventListener
メモリに関する問題
メモリ使用量が増大する問題を引き起こす方法に共通していることは、オブジェクトのメソッドをコールバックとして渡すことです。
setTimeout(obj.func, 1000); // |this| が間違って設定される!
document.addEventListener("load", obj.func, false); // |this| が間違って設定される!単純な回避策としては、無名関数をコールバックとして渡す方法があります。
document.addEventListener("load", function(event) { obj.func(event); }, false);
注意すべきなのは、この無名関数はそれを内包する環境にある全ての変数にアクセスすることができ、それらの変数が使用するメモリは、その無名関数が使われる可能性がある限りは (つまりイベントリスナが登録されている限りは) JavaScript エンジンによって解放されないということです。この関数に対して維持される必要があるのは実際には obj だけなのに、JavaScript エンジンは他の変数も維持する事を選択し、その結果メモリの負荷が増大します。removeEventListener を呼び出すか無名関数への参照を全て削除すれば、変数の消費するメモリが解放されるようになります。なので忘れずにそれを行ない、使用されていないメモリが JavaScript エンジンによって効率的に解放されるようにして下さい。