今回はBackbone.jsが依存するunderscore.jsに関する話題です。
Backbone.jsに限らず、JavaScriptではコールバック関数内でthisがグローバルのwindowを差してしまうため、この問題に対処するために、以下のようにthatやselfといった変数にthisを代入してコールバック内で使うということをすることがあると思います。
function () {
var that = this;
someFunc(function () {
this; // window
that; // 外側のthis
});
}
これでもいいですが、若干面倒ですね。こんな時、ECMAScript5で導入されたbindを使えば
function () {
someFunc(function () {
this; // 外側のthis
}.bind(this));
}
という風に書くことができますが、bindはブラウザによってはまだ実装されていなかったりするので、使うのを躊躇してしまいます。こういう時はunderscoreに定義されているbindを使えます。
function () {
someFunc(_.bind(function () {
this; // 外側のthis
}, this));
}
##underscoreの便利関数を使う場合
underscoreにはbindだけでなくmapやforEachなどのECMA Script 5の関数を模倣した関数がいくつか定義されています。実際、これらは内部でネイティブで実装されていればそちらを使用し、なければJavaScriptで模倣するように実装されています。
で、たとえばmapを使う場合でも、コールバックにthisを渡すには上記の様なthatやbindを使う必要がありますが、これらのunderscoreの関数群は関数コンテキストを渡すことができます。言葉で説明するとよくわかりませんが、つまりこういうことです。
function () {
_.map([1,2,3], function (s) {
this; // 外側のthis
}, this);
_.map([1, 2, 3], function (s) {
this; // window
});
}
ここではmapを使用していますが、他の関数も同様にコールバック関数の次にコンテキストを渡すことができるので、上手に使えば、コードを綺麗に保つことができます。
もちろん、いかなる場合でもthatやselfを用いる、というのでも問題ないでしょう。