thisはどこ?問題解決

で、javascript ちゃんとやりだして、
最初に躓いたっていうか、イマイチ腑に落ちなかったのが
いつの間にか this がどこかいってしまう問題。
多分、初歩的な問題なんだろうけど。


XMLHTTPRequest で callback 指定する時とか、
setTimeout とかの時に、クラスのメソッドを参照渡しすると、
そのクラスの属性が参照できなくなってしまう件である。

function hoge() {
    this.test = 'hello';
}
hoge.prototype = {
    fuga: function() {
      alert(this.test);
    }
}
var hoge_ = new hoge;

//この実行結果は undefined になる。ハズ。
setTimeout(hoge.request, 100);

まあ首をかしげながら、変数をグローバルにしたり、
callback に渡すのはメソッドじゃなくて関数にしたり、
挙句の果てにその関数の中でクラスをもう一度インスタンス化したりして
解決(なかったことに)してたんだけど、


今から思えばまさに迷走である。


こんな感じでやってた。テストしてないので、動くかどうかは知らんです。
動いてもしょうがないし。

var g={}

function hoge() {
   g.param='global';
   g.text = '';
}

function hoge.prototype = {
    request: function() {
        var myAjax = new Ajax.Request(
			url, 
			{
				method: 'get', 
				parameters: pars, 
				onComplete: getResponse
			});
		
    },
    
    display: function() {
        alert(g.param + g.text);
    }
}

function getResponse(o) {
    var ins = new hoge();
    ins.text = o.responseText;
    ins.display();
}

function init() {
    var ins = new hoge();
    ins.request();
}

Event.observe(window, 'load', init, false);

オブジェクト指向に片思いしてる自分としては、
クラスはそれなりに意味のあるものにしたい。
だから、問い合わせ→データ取得→出力を何とか
一つのクラス内で行いたくって四苦八苦してるのである。
あと、グローバルもなるべく汚したくないしね。


まあ、これで何となく動いてるし、まいっか。
検索してもパキッと出てこないし。
みんなどうしてんだろうとも思うんたけど、
近くの人に聞いてみても、
「this がどっかいっちゃうんですよね〜」
「うにゃむにゃむにゃ」って答えだったので、(十中八苦、聞き方が悪い)
放置してた。


これが最近になってなんとなく解決した。
参照を渡せるのは、 php でいうところの static なメソッドのみなんだ。きっと。


だから、 XMLHTTPRequest で callback 指定する時とか、
setTimeout とかの時に this がなくなっちゃうのだ。


これを解決するには、インスタンスグローバル変数にしてしまえばよい。ハズ。
で、参照渡しされるメソッド内でのみ、そのグローバル変数インスタンスを使用すればよい。ハズ。


相変わらず、テストはしてないす。

var g={}
function hoge() {
   this.param='global';
   this.text = '';
}

function hoge.prototype = {
    request: function() {
        var myAjax = new Ajax.Request(
			url, 
			{
				method: 'get', 
				parameters: pars, 
				onComplete: g.hoge.getResponse
			});
		
    },
    
    display: function() {
        alert(this.param + this.text);
    }, 

    getResponse: function(o) {
        g.hoge.text = o.responseText;
        g.hoge.display();
    }

}


function init() {
    g.hoge = new hoge();
    g.hoge.request();
}

Event.observe(window, 'load', init, false);

apply っていう関数使えば何とかなるんじゃないかとも思ったけど、
多分、これ違う。


つーことで体で覚えた javascript の作法でした。
ほんとの正解はどんななんだろう。