[JavaScript]コールバック関数とthisキーワード

JavaScriptでajaxを利用したコードを書く場合、コールバック関数を利用することが多いと思います。 ところがこういう処理をライブラリ化する際、コールバック関数内で「this」を使うと上手く動作しないことがあります。

これは、クラスメソッド内で使用する無名関数(というか入れ子の関数)の仕様が原因のようです。

以下のコードを見て下さい。

var classA = function(){
	this.sample="Hellow World";
};
classA.prototype = {
	methodA : function(){
		var dummyFunc = function(){
			document.write(this.sample);
		};
		dummyFunc();
	}
};

var objA = new classA();
objA.methodA();

上記のコードは、クラス「classA」を定義し「methodA」を実装しています。 そしてインスタン化して「methodA」を実行するものです。 期待される実行結果は当然、コンストラクタで定義しているプロパティ「sample」の値が出力されることですが、これではうまく動きません。

「methodA」の中で「dummyFunc」という関数を定義し、これを実行しているのですが、入れ子の関数内では「this」の自分自身を表さなくなってしまいます。つまりこの中の「this.sample」は自身のプロパティーを示していないことになります。

この仕様は「バグじゃないの?」と疑いたくなるような理不尽な仕様に見えますが、 対処するには入れ子関数でthis使うときはキャッシュしてから使えば解決できます。つまり・・

var tmpThis = this;
var dummyFunc = function(){
	document.write(tmpThis.sample);
};
dummyFunc();

とすれば動くようです。

クラス内で関数を入れ子にする場面は少ないですが、 コールバック関数では当然入れ子の関数を利用するのでこの問題が出てくる可能性がありますね。