関数のバインディング


この章で少し分かり辛かった、関数のバインディングについてメモ。

バインディングとは、関数のなかでthisが参照するオブジェクトを実行時に結合すること。

function getName(){
    return this.name
}

getName();
// -> ''

window.name="Demo";

getName();
// -> 'Demo'

デフォルトでは、いずれのオブジェクトにも属さない形で定義された関数は、windowオブジェクトにバインドされる。

ただし、関数を呼び出すと気に特定のオブジェクトを使用しないと、そのバインディングを失ってしまうらしい。

            var CoolObj = {
                name: 'Joe the cool object',
                
                getName: function(){
                    return this.name;
                }
            };
            window.name = '';

            //getNameはCoolObjにバインドされている
            CoolObj.getName();
            // -> 'Joe the cool object'
            
            function callFx(fx){
                return fx();
            }

            //関数の引数としてメソッドを渡すと、バインドがデフォルトのwindowに戻ってしまう
            callFx(CoolObj.getName);
            // ->''

            window.name = 'The window';
            callFx(CoolObj.getName);
            // ->'the window'

この問題を避けるために、Prototypeではbind()という関数が用意されている。

var CoolObj = {
  name: 'Joe the cool object',

  getName: function() {
    return this.name;
  }
};

CoolObj.getName()
// -> 'Joe the cool object'

function callFx(fx) {
  return fx();
}

callFx(CoolObj.getName.bind(CoolObj))
// -> 'Joe the cool object'

引数の事前設定(カリー化)

メソッドをいろんなところに渡すとき、事前に引数を設定しておくと便利!なときに使う関数。

//split()に引数':'を渡してやりたいとき
//ふつうなら…
String.prototype.splitOnColons = function(){ return this.split(':');

'1:2:3:4'.splitOnColons();
// ->["1", "2", "3", "4"]

//curry()を使うと…
String.prototype.splitOnColons = String.prototype.split.curry(':');