javascriptのthisではまったらprototype.jsのbind()を思い出してください
spamメール面白がってただけじゃなくて一応DamMapsの開発してました。地図上にダム出るようになったよ。
で、「Javascriptでオブジェクト指向だ、継承とかしちゃうぞー、テンプレートパターンだ、わーい。」みたいな感じで作っていたのですが、オブジェクトのメソッドを他に渡すような場面(例えばイベントハンドラの登録とか)でメソッド内のthisが元のオブジェクトの参照ではなくなってしまうという問題にぶち当たりしばらくはまってました。ググってみると解決法まで含めた解説がいくつか載ってたのですが(fladdict.net blog: JavaScript, ActionScriptにおける .this とは何なのか?,http://d.hatena.ne.jp/brazil/20051004/1128435079)インスタンスのローカル変数にただ格納しただけだと、そのクラスが生成したオブジェクトでその変数が全部共用されてしまい結局インスタンスが1つしか作れない。これは困った。
で、1日ほど途方にくれていたのですが、そういえば他の人はどうやってるんだろう、と気になってjavascript使ってそうなサイトのソースコードを漁ってみると、イベントハンドラとして渡すときに"メソッド名.bind(this)"って渡してる。なんだこれ、とググってみるとどうやらprototype.jsでfunctionに拡張してくれるメソッドの一つで、この引数に渡したオブジェクトのコンテキストでイベントが呼ばれたときに動作してくれるようにするための物と判明、これだ!
「スーパーpre記法 シンタックス・ハイライト」という、来週あたりはてなちゃんが必殺技として叫んでたりしそうなはてダの新機能を利用してまとめると、
var Dam = function(){}; Dam.prototype = { name:"", openGate:function(){ window.alert(this.name + "放流開始♪"); //このthisが曲者 } } var shimokubo = new Dam(); shimokubo.name = "下久保ダム"; shimokubo.openGate(); //これはうまく行く var toneDam; var name = "お風呂"; toneDam = shimokubo.openGate; toneDam() //これはうまく行かない
を実行すると1回目は下久保ダムが放流されますが、toneDam変数にメソッドを渡してtoneDam変数から呼んで見ると、お風呂の栓が抜けちゃいます。これじゃあ、困るのでprototype.jsを組み込んだ上で
var Dam = function(){}; Dam.prototype = { name:"", openGate:function(){ window.alert(this.name + "放流開始♪"); } } var shimokubo = new Dam(); shimokubo.name = "下久保ダム"; shimokubo.openGate(); //これはうまく行く var toneDam; var name = "お風呂"; toneDam = shimokubo.openGate.bind(shimokubo); //bind()でshimokuboオブジェクトを渡す toneDam() //遠隔操作もばっちり
これで、利根川ダム統合管理事務所からもコントロールできるようになりました。良かった良かった。
世の中、自分が困ってることは大体他人も困ってて、時々すでに解決されていたりするもんなんですよね。っていうか、prototype.jsちゃんと勉強しとけって話ですよね。$()とajax関係しか使ってなかった…。あ、あとイテレータも。