简体   繁体   中英

When do I need to use _.bindAll() in Backbone.js?

I am learning backbone.js, and feel confused on this: I am following the tutorial : http://arturadib.com/hello-backbonejs/

as you can see in the first example (1.js):

(function($){
  var ListView = Backbone.View.extend({    
    el: $('body'), // attaches `this.el` to an existing element.

    initialize: function(){
      _.bindAll(this, 'render'); // fixes loss of context for 'this' within methods

       this.render(); // not all views are self-rendering. This one is.
    },

    render: function(){
      $(this.el).append("<ul> <li>hello world</li> </ul>");
    }
  });

  var listView = new ListView();      
})(jQuery);

But if I comment out the sentence: _.bindAll(this, 'render'); , this will still work. I have searched in google and someone said that the method bindAll() is necessary since if I switched my context, the calling of this.render may unavailable. I feel confused on the "context". and also could some one explain me when the calling ( this.render ) will unavailable?

For the example you've given _.bindAll(this, 'render'); isn't necessary but if you have callback functions where this can possibly be changed to the context of something else, then _bindAll() can be handy.

For instance:

initialize: function(){
  _.bindAll(this, 'render', 'clickFunc');
},
events: {
   'click .someElement': 'clickFunc'
},
clickFunc: function(e) {
   /** If you remove the clickFunc from the list of events in bindAll, 
          'this' will refer to the element that invoked the event.

       Adding the clickFunc event in the _.bindAll, ensures that 'this' stays
          as the view.
   */
  this /** <-- our focal point */
}
  • Any methods listed as property values in your view's events hash are automatically bound for you by backbone
  • Any methods in your view that you manually use as event handlers from models or collections should be manually bound via bindAll
    • OR you can provide a context when you register the binding
    • OR you can use EMCA 5's function.bind to get the same result

snippet:

events: {
    'click .win': 'win',
    'click .lose': 'lose'
},
initialize: function () {
    //win and lose are automatically bound for you
    //because they are in the events property

    //refresh must be manually bound
    this.model.on('change', this.refresh);

    //which you can do ECMA5 style if you like
    this.model.on('change', this.refresh.bind(this));

    //OR you can provide a context backbone style
    this.model.on('change:foo', this.fooChange, this);

    //However, since you pretty much never want an unbound function
    //in a view, you can just stick this in all your initialize methods
    //and call it done
    //Note this will bind all functions in your view class if you don't
    //pass specific method names. I recommend this form.
    _.bindAll(this);
},
win: function () {...},
lose: function () {...},
refresh: function () {...},
fooChange: function() {...}

... OOOOORRRR just use CoffeeScript and fat arrows and solve this cleanly at the language level.

in this instance you don't need the _.bindAll , but let's say your view have a method that causes a rerender and you do something like this:

..,
myMethod: function() {
    this.$('.someselector').change(this.render);
},

if you don't have _.bindAll for render , your context would be off.

Lets take a close look at what _.bindAll does from underscore.js offical docs .

  _.bindAll = function(obj) {
    var i, length = arguments.length, key;
    if (length <= 1) throw new Error('bindAll must be passed function names');
    for (i = 1; i < length; i++) {
      key = arguments[i];
      obj[key] = _.bind(obj[key], obj);
    }
    return obj;
  };

What it does is to automatically bind all its functions to its correct context. (where its function is declared rather than invoked.

I personally think it was a convention for old version of Backbone.js to bind its events , or DOM action listeners. Since new versions Backbone View automatically bind and unbind listeners in events . Find more by search Binding "this" here

I hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM