• louis vuitton outlet
  • nike air max
  • ray ban uk
  • oakley sunglasses outlet
  • cheap jordan shoes
  • toms outlet
  • Cheap Oakleys Sunglasses
  • fifa coins
  • ray ban
  • cheap uggs
  • ray ban uk
  • nike air max
  • ray ban outlet
  • burberry uk
  • fut coins
  • fut 14 coins
  • fut coins
  • Christian Louboutin Outlet
  • michael kors outlet
  • coach outlet
  • louis vuitton outlet
  • fifa coins
  • ray ban
  • Custom iphone cases
  • nike
  • monster beats
  • nike outlet
  • Christian Louboutin Outlet
  • burberry outlet
  • coach outlet
  • iphone cases
  • LV
  • new balance
  • Getting Into Context Binds

    Getting Into Context Binds

    On February 12, 2013, in JavaScript, by Jim Cowart

    I was source-diving a Backbone.js application recently and noticed the liberal use of _.bindAll(this) calls throughout the code base. Then, in another jQuery-heavy application, I noticed frequent use of the $.proxy() call. In the past, I have certainly been guilty of the former – you know the “What the heck is ‘this’, this time? Nuke it from orbit and just bind all the methods!” But seeing it so often in others’ code made me wonder – are they aware of what’s happening? You probably are, but let’s look anyway:

    var Person = function( name ) {
        this.name = name;
    };
    Person.prototype.greet = function() {
        return "Oh, hai " + this.name;
    };
    Person.prototype.sayBye = function() {
        return "Get lost, " + this.name;
    };
    
    var me = new Person("Jimbabwe");
    

    Inspecting the above instance will show us something similar to this:

    Inspecting the person instance

    Notice that the “greet” and “sayBye” methods appear on the prototype of “Person”.

    Now let’s pretend that we’ve gotten terribly frustrated because our “greet” method is being invoked asynchronously (we assigned it as the click event handler on a fictional ‘greet’ button), and we’re consistently seeing “Oh, hai undefined”. In our frustration, we “brute force” the context to be the proper “this” by doing, well, this:

    // assuming underscore is present....
    var Person = function( name ) {
        this.name = name;
        _.bindAll( this );
        // FYI, an alternative to the above _.bindAll could be:
        // _.bindAll( this, "greet", "sayBye");
        // args following the context specify method names to bind
    };
    Person.prototype.greet = function() {
        return "Oh, hai " + this.name;
    };
    Person.prototype.sayBye = function() {
        return "Get lost, " + this.name;
    };
    
    var me = new Person("Jimbabwe");
    

    Now, when we inspect the “me” instance, we’ll see something like this:

    inspecting the bound instance

    That’s right – using .bind, .bindAll, $.proxy or even plain ES5 Function.prototype.bind() to bind the “this” context results in an instance-level method. This should be obvious, right? Surprisingly enough, many of the people I’ve talked to haven’t stopped to think about this. That sound you hear is the mini-Crockford-angel (or devil, perhaps) on your right shoulder, reminding you that by creating instance-level methods, you’ve erased the gain of having methods on the prototype. If the method stays on the prototype, it’s created once and then shared by future “Person” instances. There is a very real memory and CPU performance loss in wastefully assigning instance members when you don’t need to.  Consider this:

    Performance Comparison

    All three tests use the same prototype – where “Normal” has no context binding, and the others use underscore and jQuery, respectively, to bind the context of the prototype methods in the constructor functions.

    Ok – so we’ve established that explicitly binding the context of a prototype method creates an instance level method, as well as the fact that doing so unnecessarily can result in a serious performance drop – but are there any other potential gotchas? I can think of at least one – stealing a bound method:

    var Person = function( name ) {
        this.name = name;
        _.bindAll( this );
    };
    Person.prototype.greet = function() {
        return "Oh, hai " + this.name;
    };
    Person.prototype.sayBye = function() {
        return "Get lost, " + this.name;
    };
    
    var me = new Person("Jimbabwe");
    
    var obj = { name: "Eduardo" };
    
    me.greet.call(obj);
    // "Oh, hai Jimbabwe"
    

    I’m going to go ahead and concede that I have no idea why someone, in their right mind, would need to steal the “greet” method from the “me” instance and call it on “obj” – as long as you concede to me that there’s no end to the unpredictability of developers doing crazy nonsensical things after you’ve bequeathed a pristine codebase to them. But the point still stands – it’s important to realize that once you’ve bound the method, it’s bound. The only way around unexpected side effects in the above example would be to call “Person.prototype.greet.call(obj);” – probably not a bad practice in general, should you need to steal methods at some point.

    Hold On a Second, Let’s Back Up

    This begs the question – why did the developer feel the need to bind the method to begin with? “This” wasn’t what they expected or needed, of course! But why does that happen? When “greet” is invoked on the “me” instance, it’s invoked as a method. The context – “this” – points to the instance. However – what happens when we take that method and assign it as the callback to be invoked when an event occurs? The event will invoke the callback asynchronously – at some point when (in this case) we click the button:

    $("#greeter").on("click", me.greet);
    

    When the event occurs, the element will own the context as the callback is invoked. When the function attempts to access “this.name”, it will get an undefined value. Avoiding this error is obviously important, but does it have to be solved by binding all the prototype methods to the instance? No! You can bind at the point of subscribing to the event:

    // using $.proxy
    $("#greeter").on("click", $.proxy(me.greet, me));
    
    // using _.bind
    $("#greeter").on("click", _.bind(me.greet, me));
    
    // using ES5 (or a shim)
    $("#greeter").on("click", me.greet.bind(me));
    

    Some eventing libraries provide explicit facilities to let you specify the context, without having to actually pass a bound function. (In fact, Backbone binds the context of your DOM event handlers automatically to the view for you as it wires them up.) Under the hood, many (but not all) of those libraries are typically using call/apply to pass the context to the function as it is invoked.

    // postal subscription on a channel
    var sub = channel.subscribe("my.topic", callback)
                     .withContext(something);
    
    // Backbone Events - can pass context as optional 3rd arg
    someModel.on("change:firstName", doStuff, this);
    

    It’s a safe assumption that not every method on your instances will be invoked asynchronously, as a handler to an event. So – binding the context on an as-needed basis (as you register event callbacks) will have a much more performance-friendly CPU & memory footprint.

    Ok, so:

    • Binding prototype methods creates instance level methods? Check.
    • Instance level methods are created each time the instance is, and result in decreased performance? Check.
    • Stealing bound methods can violate the principle of least surprise? Check.
    • It’s better to only bind the context in situations that actually will result in changed context? Check.

    Is there anything else we should be aware of? Yes:

    // using _.bind on me.greet
    $("#greeter").on("click", _.bind(me.greet, me));
    
    // This will not remove the event handler
    $("#greeter").off("click", me.greet);
    

    The above example is stating the obvious, I know. But it’s a good reminder that binding the context of a function produces a new function. If you plan to remove the event subscription, you’ll need to either hang on to a reference to the bound function to remove it specifically, use a namespace to separate it from other handlers, or be willing to clear all the events, etc. Also – it’s worth noting that jQuery goes a bit further with $.proxy, so that it’s possible to unbind a bound handler by passing the original function reference as opposed to the bound one. Regardless, though, jQuery’s own documentation still recommends that you use event namespaces.

    So – armed with this – may your binding be bind-free….

    Tagged with:  
    • http://www.facebook.com/jcreamer898 Jonathan Creamer

      Such great stuff in here! I had no idea about _.bindAll creating instance methods. Thanks man!

    • http://twitter.com/tehsuck Chiefus Baltar

      I had no idea _.bindAll was such a costly thing. Thanks!

    • http://twitter.com/_posbo Paul Osborne
    • Pingback: YUI Weekly for February 15th, 2013 - YUI Blog

    • roblevintennis

      Very nice break down on some drawbacks of overly zealous self bind; thanks!

    • maxw3st

      I like “this” solution by Evan Prodromou in “this” week’s JavaScript Weekly:

      Person.prototype.setAge = function(newAge) {
      var person = this;
      person.age = newAge;
      });

      Skip the binding, use a variable with function level scope and no external libraries. http://evanprodromou.name/2013/02/08/on-using-this-exactly-once/?utm_source=javascriptweekly&utm_medium=email

      • http://ifandelse.com Jim Cowart

        @maxw3st – unfortunately aliasing “this” with a different variable doesn’t solve the problem if you have assigned the setAge function to be invoked as the callback to an event. If setAge is the handler, the this context will be the element (assuming the handler wasn’t delegated to a different element or otherwise hijacked) – regardless, it won’t be the person instance unless you bind it, or otherwise wrap setAge by passing an anonymous function as the callback and invoking setAge as method on the instance inside the callback. In the example you posted above, if setAge was the handler reference, you would simply be aliasing the element as “person”. Aliasing “this” as another variable is done to hang on to the proper “this” context – it’s a way around binding (and can be very useful), but aliasing “this” inside a prototype method doesn’t help at all if “this” isn’t your instance when the method is invoked. Evan’s article specifically provided an example of a prototype method making an asynchronous call to a storage library. He aliased “this” as “person” and used the “person” reference inside the callback. That’s completely fine, assuming “this” as you enter the “save” function is the person instance! If “save” has been directly invoked as a callback, for example, to a save button input element, his code will throw an exception as soon as it hits person.database.insert (“cannot call insert of undefined”).

        In a nutshell, assigning “this” to another variable in a prototype method to maintain a reference to your instance is meaningless if the method is directly invoked asynchronously and hasn’t been bound.

        • the professor

          you’re correct. the reason to point a variable to “this” is typically to take advantage of closure to work around the the fact that the conext of ‘this’ will be different in a callback.. It doesn’t make a lot of sense with this example, but something like:

          Person.setAge = function(newAge) {
          var person = this;
          return function(newAge) {
          person.age = newAge;
          }
          };

          then you might say…

          doSomeAsyncOperation(Person.setAge());

          where doSomeAsycnOperation’s parameter is a callback function.

          • http://ifandelse.com Jim Cowart

            The point I was making was in regards to getting a reference to “this” in a *prototype* method. What you’ve described above would be an instance method that you are binding (via the fn closing around ‘person’). I quote Tessler’s Law of Conservation of Complexity a lot: “you cannot reduce the complexity of a task beyond a certain point. Once you reach that point, you can only shift the burden around.” In this, you’ve shifted the burden to creating instance methods by calling “setAge” in order to get a bound function that can actually, then, set the age. While this is certainly do-able, I would be concerned that the API would be a bit unclear, as I would expect calling “setAge” to allow me to actually set the age, rather than act as a factory for a function that can. However, if I put this method on the prototype and then bind it when I pass it to ‘doSomeAsyncOperation’, I get the benefit of binding *only* when I truly need to, keeping unnecessary instance-level members to a minimum. Thanks for reading!

    • Geoff

      Fantastic Article. Really cleared up a lot of questions that I had.

    • Pingback: Seven JavaScript Quirks I Wish I’d Known About | Telerik Developer Network

    • Pingback: 我希望我知道的七个JavaScript技巧 - javascript教程 - 开发者

    • Pingback: 我希望我知道的七个JavaScript技巧 - javascript - 开发者第2458015个问答

    • http://twitter.com/_posbo Paul Osborne

      Thanks for the reply Jim, i’m smoothing out a few rough spots in my work thanks to the material you are posting – keep it up man :)