読者です 読者をやめる 読者になる 読者になる

[JavaScript] jQueryの$.proxy

JavaScriptでcallback処理で呼元のthisを参照したい時がよくあります。
例えば、下のような感じです。

var Hoge = function(name){
    this.name = name;
};
Hoge.prototype.method = function(){
	var url = '';
	var param = {};
	$.post(url, param, function(data){
		alert(this.name);
	});
};
var hoge = new Hoge('aaa');
hoge.method();

で、thisの中身はHogeではないので、postのundefinedがalertに表示されます。
これを解決するには、以下のようにbindメソッドを使うとOKです。

Hoge.prototype.method = function(){
	var url = '';
	var param = {};
	$.post(url, param, function(data){
		alert(this.name);
	}.bind(this));
};

だがしかし!!bindはECMAScript5で追加されたので、IE8では動かないのです。
それを解決するには、jQueryの$.proxyを使うと楽にいけます。

Hoge.prototype.method = function(){
	var url = '';
	var param = {};
	$.post(url, param, $.proxy(function(data){
		alert(this.name);
	}, this));
};

じゃぁ、JQueryが使えない時どうするのか??というか、proxyの中身ってどうなってるのか?
ソースをみるとapplyを使っていました。
傍らにあるパーフェクトJavaScriptの185ページを読むと、bindとapplyの違いは以下のようになっていました。

  • bindはその場で実行せずにクロージャを返却
  • apply(call)はその場で実行

ということで、proxyの中身はapplyを実行する関数を返してあげればOKなのかなと。

function proxy(fn, context){
	var proxy = function(){
		return fn.apply(context, arguments);
	};
	return proxy;
}

var Hoge = function(name){
    this.name = name;
};
Hoge.prototype.method = function(){
	var url = '';
	var param = {};
	$.post(url, param, proxy(function(data){
		alert(this.name);
	}, this));
};
var hoge = new Hoge('aaa');
hoge.method();

これですっきり寝れるや。