Mach3.laBlog

“bind” – Alphabetical Advent Calendar 2013

この記事は賞味期限切れです。(更新から1年が経過しています)

“B” は bindの “B”。

B

Function.prototype.bind

function に生えている bind メソッドは、関数の “this” を他のオブジェクトに固定する事ができます。 役割は call/apply と似ていますが、即実行されるのではなく function を返す点で異なります。

Function.prototype.bind – JavaScript | MDN

イベントハンドラの登録等でよく使っています。

var app = {
    name: "app",
    el: null,
    init: function(){
        this.el = document.getElementById("myform");
        this.el.addEventListener("submit", this.onSubmit.bind(this), false);
    },
    onSubmit: function(e){
        e.preventDefault();
        // 通常ここの"this"はHTMLFormElementですが、
        // bindされているので"this"はappオブジェクトになります
        console.log(this.name); // "app"
        var form = e.target; // フォームエレメントを取得する時は引数から
    }
};
app.init();

引数を追加する

bindは第二引数以降で、関数に渡す引数を追加することができます。

var app = {
    name: "app",
    el: null,
    init: function(){
        this.el = document.getElementById("myform");
        this.el.addEventListener("submit", this.onSubmit.bind(this), false);
    },
    onSubmit: function(a, b, c){
        // 追加引数は先頭に追加される
        c.preventDefault();
        console.log(arguments); // "foo", "bar", Event
    }
};
app.init();

注意が必要なのは、追加の引数は先頭に追加される点。 はじめの引数をイベントオブジェクトだと思って preventDefault したけど動かなかった! なんてことがないようにしましょう。

removeEventListener できない問題

関数を bind して addEventListener で登録した後、removeEventListener しようとするとうまく動かない場合があります。

el.addEventListener("click", someHandler.bind(someObj));

// 以下の両者とも、remove できない
el.removeEventListener("click", someHandler);
el.removeEventListener("click", someHandler.bind(someObj));

これは、bind が function を無名変数でラップして別の物にして返してしまう為です。 removeEventListener でイベントハンドラを解除する為には、addEventListener で設定した物と同一でなければなりません。

例えば、bind で返った function を一度変数に格納する事で、回避する事ができます。

var boundHandler = someHandler.bind(someObj);
el.addEventListener("click", boundHandler);

// remove できる
el.removeEventListener("click", boundHandler);

あるいは、下記参考リンクのように handleEvent を使う手もあるようです。

jQuery.fn.proxy

bindと似た役割をもつメソッドがjQueryのproxyメソッドです。追加の引数も bind と同様に使えます。

jQuery.proxy() | jQuery API Documentation

$("#myform").on("submit", $.proxy(this.onSubmit, this));

jQueryを使用しているならこれで十分役割を果たせますが、 特に理由がなければ既に定義されているbindを使って行った方が自然だと思います。

使える環境

bind メソッドはEcmaScript5で定義されていますが、勿論古いブラウザでは使えない場合があります。 IEで対応しているのが9以降なので、8以前でも使いたい場合は MDNにあるコード を使用するか、es5-shim.js に頼るか、自前で定義しておく必要があります。

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*