関数の再代入時のthis
オブジェクトのプロパティメソッドを一旦変数に代入してやるとthisの所在がかわってしまうのでそれについて
(function(){ var obj = { hoge: 'abc', moge : function() { console.log(this.hoge); } }; obj.moge(); // abc }());
普通にオブジェクトのプロパティを実行する分には問題なし
実行時にmogeメソッドのthisはobjをさしてるから
次に、オブジェクトのプロパティメソッドを変数に再代入する
(function(){ var obj = { hoge: 'abc', moge : function() { console.log(this.hoge); } }; var method = obj.moge; method(); // undefined }());
これはNG
なぜなら method = obj.moge の代入処理時にthisの値が = の左辺になってしまってうから
代入実行時にmethodはオブジェクトではないのでthisはグローバルをさしてしまう
というわけでthisを束縛してあげるproxy関数を作って間に一枚かますとok
(function(){ var obj = { hoge: 'abc', moge : function() { console.log(this.hoge); } }; function proxy(fn, obj){ return function(){ return fn.call(obj); } } var method = proxy(obj.moge, obj); method(); // abc }());
これならproxyのおかげでthisとしてobjを束縛してるのでok
引数とれないと色々不都合あるので引数とれるようにしてあげる。
(function(){ var obj = { hoge: 'abc', moge : function(a, b, c, d) { console.log(this.hoge); console.log([a, b, c, d]); } }; function proxy(fn, obj){ return function(/* arguments */){ var args = Array.prototype.slice.call(arguments); return fn.apply(obj, args); } } var method = proxy(obj.moge, obj); method(1, 2, 3, 4); // abc , [1,2,3,4] }());
これで大体の場合はok
追記
teramako先生からご指摘をいただきました!
新しいブラウザならjavascript1.8.5からFunction.prototype.bindが追加されているのでそれを利用するといいです。
(function(){ var obj = { hoge: 'abc', moge : function(a, b, c, d) { console.log(this.hoge); console.log([a, b, c, d]); } }; var method = obj.moge.bind(obj); method(1, 2, 3, 4); // abc , [1,2,3,4] }());
ちなみにこれはff4, ie9, chrome7,opera11.6以降から使えます
ご指摘ありがとうございました><