Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Understanding JavaScript’s Function.prototype.bind

Function binding is most probably your least concern when beginning with JavaScript, but when you realize that you need a solution to the problem of how to keep the context of this within another function, then you might not realize that what you actually need is Function.prototype.bind().

The first time you hit upon the problem, you might be inclined to set this to a variable that you can reference when you change context. Many people opt for self, _this or sometimes context as a variable name. They’re all usable and nothing is wrong with doing that, but there is a better, dedicated way.

Jack Archibald tweets about1 caching this:

It should have been more apparent to me when Sindre Sorhus spelled it out2:

I ignored this wise advice for many months.

What Problem Are We Actually Looking To Solve? Link

Here is sample code in which one could be forgiven for caching the context to a variable:

var myObj = {

    specialFunction: function () {

    },

    anotherSpecialFunction: function () {

    },

    getAsyncData: function (cb) {
        cb();
    },

    render: function () {
        var that = this;
        this.getAsyncData(function () {
            that.specialFunction();
            that.anotherSpecialFunction();
        });
    }
};

myObj.render();

If we had left our function calls as this.specialFunction(), then we would have received the following error:

Uncaught TypeError: Object [object global] has no method 'specialFunction'

We need to keep the context of the myObj object referenced for when the callback function is called. Calling that.specialFunction() enables us to maintain that context and correctly execute our function. However, this could be neatened somewhat by using Function.prototype.bind().

Let’s rewrite our example:

render: function () {

    this.getAsyncData(function () {

        this.specialFunction();

        this.anotherSpecialFunction();

    }.bind(this));

}

What Did We Just Do? Link

Well, .bind() simply creates a new function that, when called, has its this keyword set to the provided value. So, we pass our desired context, this (which is myObj), into the .bind() function. Then, when the callback function is executed, this references myObj.

If you’re interested to see what Function.prototype.bind() might look like and what its doing internally, here is a very simple example:

Function.prototype.bind = function (scope) {
    var fn = this;
    return function () {
        return fn.apply(scope);
    };
}

And here is a very simple use case:

var foo = {
    x: 3
}

var bar = function(){
    console.log(this.x);
}

bar(); // undefined

var boundFunc = bar.bind(foo);

boundFunc(); // 3

We’ve created a new function that, when executed, has its this set to foo — not the global scope, as in the example where we called bar();.

Browser Support Link

Browser Version support
Chrome 7
Firefox (Gecko) 4.0 (2)
Internet Explorer 9
Opera 11.60
Safari 5.1.4

As you can see, unfortunately, Function.prototype.bind isn’t supported in Internet Explorer 8 and below, so you’ll run into problems if you try to use it without a fallback.

Luckily, Mozilla Developer Network, being the wonderful resource it is, provides a rock-solid alternative5 if the browser hasn’t implemented the native .bind() method:

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

Patterns For Usage Link

When learning something, I find it useful not only to thoroughly learn the concept, but to see it applied to what I’m currently working on (or something close to it). Hopefully, some of the examples below can be applied to your code or to problems you’re facing.

Click Handlers Link

One use is to track clicks (or to perform an action after a click) that might require us to store information in an object, like so:

var logger = {
    x: 0,
    updateCount: function(){
        this.x++;
        console.log(this.x);
    }
}

We might assign click handlers like this and subsequently call the updateCount() in our logger object:

document.querySelector('button').addEventListener('click', function(){
    logger.updateCount();
});

But we’ve had to create an unnecessary anonymous function to allow the this keyword to stand correct in the updateCount() function.

This could be neatened up, like so:

document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));

We’ve used the subtly handy .bind() function to create a new function and then set the scope to be bound to the logger object.

setTimeout Link

If you’ve ever worked with templating engines (such as Handlebars) or especially with certain MV* frameworks (I can only speak of Backbone.js from experience), then you might be aware of the problem that occurs when you render the template but want to access the new DOM nodes immediately after your render call.

Suppose we try to instantiate a jQuery plugin:

var myView = {

    template: '/* a template string containing our <select /> */',

    $el: $('#content'),

    afterRender: function () {
        this.$el.find('select').myPlugin();
    },

    render: function () {
        this.$el.html(this.template());
        this.afterRender();
    }
}

myView.render();

You might find that it works — but not all the time. Therein lies the problem. It’s a rat race: Whatever happens to get there first wins. Sometimes it’s the render, sometimes it’s the plugin’s instantiation.

Now, unbeknownst to some, we can use a slight hack with setTimeout().

With a slight rewrite, we can safely instantiate our jQuery plugin once the DOM nodes are present:

//

    afterRender: function () {
        this.$el.find('select').myPlugin();
    },

    render: function () {
        this.$el.html(this.template());
        setTimeout(this.afterRender, 0);
    }

//

However, we will receive the trusty message that the function .afterRender() cannot be found.

What we do, then, is throw our .bind() into the mix:

//

    afterRender: function () {
        this.$el.find('select').myPlugin();
    },

    render: function () {
        this.$el.html(this.template());
        setTimeout(this.afterRender.bind(this), 0);
    }

//

Now, our afterRender() function will execute in the correct context.

Tidier Event Binding With querySelectorAll Link

The DOM API improved significantly once it included such useful methods as querySelector, querySelectorAll and the classList API, to name a few of the many.

However, there’s not really a way to natively add events to a NodeList as of yet. So, we end up stealing the forEach function from the Array.prototype to loop, like so:

Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
    el.addEventListener('click', someFunction);
});

We can do better than that, though, with our friend .bind():

var unboundForEach = Array.prototype.forEach,
    forEach = Function.prototype.call.bind(unboundForEach);

forEach(document.querySelectorAll('.klasses'), function (el) {
    el.addEventListener('click', someFunction);
});

We now have a tidy method to loop our DOM nodes.

Conclusion Link

As you can see, the .bind() function can be subtly included for many different purposes, as well as to neaten existing code. Hopefully, this overview has given you what you need to add .bind() to your own code (if necessary!) and to harness the power of transforming the value of this.

(al, il)

Footnotes Link

  1. 1 https://twitter.com/jaffathecake/
  2. 2 https://twitter.com/sindresorhus/
  3. 3 https://twitter.com/benhowdle
  4. 4 https://twitter.com/search?q=%24this&src=ctag
  5. 5 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Advertisement

Ben Howdle is a web developer from Droitwich, UK. He works by day at Wapple.net and by night and weekends as Two Step Media. An insatiable passion for the dynamic web and exciting web applications.

  1. 1

    There is much truth in this article. Thanks for the great post.

    But at least for me, there are some cases where using .bind() can cause confusion, as I need to scroll down to the bottom of my functions scope to see that ‘this’ has been overwritten. Especially in more complex projects, I prefer relying on my own, more ‘speaking’ variables.

    Nevertheless, using .bind() appears to be more sexy than that = this; :-)

    1
  2. 2

    Binding is slow in chrome? See this test: http://jsperf.com/binding2

    2
  3. 3

    Thought it might be worth pointing out that the same can be achieved with jQuery’s $.proxy() instead of having to do $this… For example, your button click event would then look like:

    $('button').click($.proxy(logger.updateCount, logger));

    Working example here: http://jsbin.com/ELITIfo/1/edit

    5
    • 4

      Hey Jenna, ace point indeed, jQuery has a lot of these lovely abstractions and .bind() is no exception!

      1
  4. 5

    Oskar Dahlberg

    January 23, 2014 5:47 am

    Wow! This totally blew my mind. And I thought I had somewhat mastered JS :D This will change my patterns significantly. Great post!

    3
  5. 6

    I’m not a huge fan of .bind(). Technically it works fine, but reusing this within multiple nested contexts can cause confusion… using “var self = this;” or something like that creates a clear distinction between objects to avoid confusion as to which this you actually mean. It also avoids problems like in a click handler where you might want to have access to the normal “this” scope as well as your original “this” scope.

    -1
    • 7

      Hey Jon,

      Fair points indeed,

      Inside event handlers (click, for example) you can still use the passed in Event object, ie. e.currentTarget

      -1
    • 8

      Agreed, 100%. I use self or that to store my this reference for any code that nests and I have never seen a significant enough performance hit to warrant further optimization or an alternate implementation.

      0
  6. 9

    Samuel Ondrek

    January 23, 2014 2:31 am

    Awesome Article!!!

    This is also kind of nice answer about Inheritance and JS http://bit.ly/1l0Hl43 (stackoverflow)

    0
  7. 10

    Thanks for the great post. There is a typo in “this instance of fNOP”.
    It should be “instanceof”.

    0
    • 11

      Hey Jim,

      Thanks for the kind words and ace spot on the code typo! That was straight from the MDN docs as well, so they also have a typo ; )

      0
  8. 12

    Nice! Didn’t know about the bind keyword.

    Just out of curiosity – is there anything technically wrong with using that = this? Any gotchya’s we should be aware of?

    0
    • 13

      Hey Sean, nope, nothing technically wrong, just means a (potentially unnecessary) extra line of code when there’s a native solution available!

      0
      • 14

        Richard Korebrits

        February 4, 2014 12:03 am

        Hi Ben,
        This is what I don’t really get out of your article. Either use that = this (I prefer t = this) once, or you need to use `bind()` every time. How is using t = this “a (potentially unnecessary) extra line”, whereas using `bind` more than once means multiple extra lines.

        I see that in some cases it might be handy, but there is e.g. no mention of how to use `this` inside of the getAsyncData scope because `this` is set to the parent scope. What if you need to bind to the current scope?

        this.getAsyncData(function () {
        this.specialFunction();
        this.anotherSpecialFunction();
        }.bind(this));

        0
  9. 15

    In the “settimeout” section, you wrote: “However, we will receive the trusty message that the function .afterRender() cannot be found.”
    Wouldn’t the message stat that “this.$el” cannot be found instead?

    Great article, by the way.

    0
  10. 18

    Some performance tests? In some cases i revert back to the context variable because explorer hang.

    0
  11. 19

    I ran the basic object with methods and using bind in the render method through jsPerf, it looks like aside from Firefox, using the bind method might be slower. Unless I’m doing something wrong.. http://jsperf.com/prototype-bind-vs-variable-cache/2

    0
  12. 20

    Alexandr Marinenko

    January 23, 2014 9:23 am

    Ben, you defined an object logger and you use bind to solve “this” problem inside of “updateCount”. Why don’t you use “logger.x++” instead of “this.x++”?

    0
    • 21

      Hey Alexandr,

      You’re totally right, we could definitely use `logger.x++`, I’m just pointing out that if you wanted to keep things a bit more reusable/generic then, using `this.x` and not having to explicitly reference `logger` would be a little more preferable…

      0
  13. 22

    Is it me or does it seem *this* problem is better resolved by passing ‘this’ as the argument to the anonymous function? It’s explicit, doesn’t create a closure, and is one line shorter than the original source.

    var myObj = {
    specialFunction: function () {},
    anotherSpecialFunction: function () {},
    getAsyncData: function (cb, obj) {
    cb( obj );
    },
    render: function () {
    this.getAsyncData( function ( that ) {
    that.specialFunction();
    that.anotherSpecialFunction();
    });
    }
    };
    myObj.render();

    0
    • 23

      Andrew Bridge

      January 24, 2014 5:43 am

      Anonymous functions are never the better solution, they make it harder for the engine to optimise code. I have no proof, but I’d imagine that it’d be easier to optimise a function produced by bind that an anonymous function.

      I also prefer to only have to look for the “this” keyword (which editors usually recognise and highlight) rather than also having to search for “self”, “that” or whatever variable you pass it to. That’s just an opinion though!

      -1
  14. 24

    func.bind() is funny !

    But the fun goes on … ever tried something like func.bin(x)() ?

    Using func.call() or func.apply() can also lead to some nice insights into the
    elegance of Javascript

    Regards

    0
  15. 25

    Very nice article, I was facing these kind of issues and I really don’t like this that trick. thanks!

    1
  16. 26

    Another solution would be to integrate underscore.js.
    Then you can use:

    render: function () {
    _.bind(this.getAsyncData(function () {
    this.specialFunction();
    this.anotherSpecialFunction();
    }), this);
    }

    0
  17. 27

    It’s a fantastic article!

    I would appreciate if you could elaborate how the following code is better than the previous alternative:
    —-
    var unboundForEach = Array.prototype.forEach,
    forEach = Function.prototype.call.bind(unboundForEach);

    forEach(document.querySelectorAll(‘.klasses’), function (el) {
    el.addEventListener(‘click’, someFunction);
    });
    —–
    Is the former code any faster?

    0
    • 28

      Hi Vasulu,

      Thanks for commenting, the former code probably will be marginally faster as .bind() does involve some minor processing to return a new, bound function. I just feel that the latter example is slightly more readable as you would maybe store the first two lines in a utils.js/helper.js file…

      0
  18. 29

    Fantastic explanation with examples. Keep up the good work.

    0
  19. 30

    The partial implementation creates bound functions whose length property does not agree with that mandated by ECMA-262: it creates functions with length 0, while a full implementation, depending on the length of the target function and the number of pre-specified arguments, may return a non-zero length. http://eduresult.in

    if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
    if (typeof this !== “function”) {
    // closest thing possible to the ECMAScript 5 internal IsCallable function
    throw new TypeError(“Function.prototype.bind – what is trying to be bound is not callable”);
    }

    var aArgs = Array.prototype.slice.call(arguments, 1),
    fToBind = this,
    fNOP = function () {},
    fBound = function () {
    return fToBind.apply(this instanceof fNOP && oThis
    ? this
    : oThis,
    aArgs.concat(Array.prototype.slice.call(arguments)));
    };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
    };
    }

    0
  20. 31

    Something about this article finally made me figure out why I’ve never found `bind()` super intuitive — it’s the fact that it comes _after_ the function body, which means that reading the function body top to bottom you don’t know what `this` means until you get to the end. Hopefully the function body is pretty short to minimize this problem.. but still… While using `var that = this` is clunky, at least you know can read the code linearly and know what is happening.

    Still, `bind()` is the way to go.

    2

↑ Back to top