2007年11月17日土曜日

Javascript の this についてのメモ

this の扱いに困り果てたので、メモ

以下のサイトを参考にさせてもらって、イベント経由で呼び出した場合、
クラス内の this が別のものに変わってしまう点は対応できた。

[JavaScript] イベント上の this をめぐる攻防

こんな感じでクラスを書いてみる。

testFunction = function() {
this.init();
}

testFunction.prototype = {
init : function(){
this.setEvent();
},
setEvent : function() {
Event.observe($('testbButton'), 'click', this.doFunction, false);
},
doFunction : function(obj){
this.alert(obj);
},
alert: function(obj){
alert(obj.getAttribute('id')+ 'で doFunction が実行されたよ') ;
}
}

new testFunction();

HTML上にはこんなのがあるとして。
<button type="'button'" id="'testButton'">ぼたんだよ</button>


これだと、クリックしたときのに呼び出される this.Function 内の thsi が ボタンの部分を
参照してしまうので、動かない・・・Firebugで「this.console is not a function」とエラー

で上記のサイトで説明してくれてる クロージャーを使って this を 無名関数内に
閉じ込めて?あげる、、、こんな感じかな?

setEvent : function() {
Event.observe($('testbButton'), 'click', (function(obj){
return function(){
obj.doFunction(this);
};
})(this), false);
}

Firefox だと「testbButtonで doFunction が実行されたよ」ってでるけど、IE7で動かない・・・IE7 と Firefox だと this が違うみたい。

いろいろ試したり、for ~ in で表示させたりしたところ、IE7 だと window オブジェクトが this っぽい?
window オブジェクトからは イベント発生源とれなそうなので、イベントオブジェクトが関数側に渡されるので、そちらから、「event.srcElement」で取得する。
setEvent : function() {
Event.observe($('testbButton'), 'click', (function(obj){
return function(evt){
var params = Prototype.Browser.IE ? evt.srcElement : this;
obj.doFunction(params);
};
})(this), false);
}
これで IE7 でも 「testbButtonで doFunction が実行されたよ」って表示された。おしまい。

Firefox なら event.target でも取得できそうだけど、どっちを使うのがいいんだろうかとかどっちの実装が正しいんだろうか(Firefoxだろうけど)とかは Under Translation of ECMA-262 3rd Edition(邦訳)このあたり参照で。