最近になってprototype.jsの使い方を学んでみたりしているのですが、bindとbindAsEventListenerについてちょっとした疑問が出てきています。
両者の違いについては、prototype.js v1.4.0 の使い方にある説明で知ることができました。サンプルソースを引用してみます。
<input type=checkbox id=myChk value=1> Test? <script> //declaring the class var CheckboxWatcher = Class.create(); //defining the rest of the class implementation CheckboxWatcher.prototype = { initialize: function(chkBox, message) { this.chkBox = $(chkBox); this.message = message; //assigning our method to the event this.chkBox.onclick = this.showMessage.bindAsEventListener(this); }, showMessage: function(evt) { alert(this.message + ' (' + evt.type + ')'); } }; var watcher = new CheckboxWatcher('myChk', 'Changed'); </script>
このbindAsEventListenerをbindに変えてしまうと、Firefoxでは動作するのですがIEでは動作しなくなります(eventオブジェクトevtが未定義になるため)。要はbindAsEventListenerはブラウザ間の互換性を考慮した、イベントハンドラのためのbind、ということなのだと解しました。
※ Hawk's Laboratory » prototype.js 1.4.0を読む:base.jsその2 にbindAsEventListenerとbindの詳しい解説があります。
※ 更に、Hawk's Laboratory » attachEventの動作にて attachEventにより渡される引数について調べて頂きました。
ただ、この例ではイベントハンドラの登録にonclickプロパティを用いていますが、prototype.jsではEvent.observeというイベントハンドラ追加用のメソッドも定義されています。なので、イベント登録の部分を
//assigning our method to the event
Event.observe(this.chkBox, 'click', this.showMessage.bind(this));
としてみると、bindAsEventListenerでなくbindを使っているにも関わらず、IEでもFirefoxでも動作してました(Windows 2000のIE6とFirefox 1.5.0.3で確認)。
Event.observeの実装を見てみると、DOM2 Event仕様にあるaddEventListenerが使えるときはそれを使い、そうでなければattachEvent(IEでの実装)を使うようになっていました。それでattachEventについて試してみたのですが、どうもattachEventでイベントハンドラを登録した場合には、イベントハンドラの引数としてイベントオブジェクトらしきものがちゃんと渡されているようです。
というわけで、イベントハンドラを登録するときはonXXXXXのようなプロパティなぞを使わずに、(より標準っぽい)Event.observeを使っておけば、bindAsEventListenerを使う必要はないのでは? という疑いを持ち続けています。しかしわざわざbindと別にメソッドを定義しているのには何か理由があるのかもしれず、詳しい方の意見をお聞きしてみたいところなのです。