need explanation of the _.bindAll() function from Underscore.js
I've been learning some backbone.js and I've seen plenty of instances where _.bindAll()
is used. I have read through the entire backbone.js and underscore.js documentation page to try to get a sense of what it does, but I still am very fuzzy as to what it does. Here is underscore's explanation:
_.bindAll(object, [*methodNames])
Binds a number of methods on the object, specified by methodNames, to be run in the context of that object whenever they are invoked. Very handy for binding functions that are going to be used as event handlers, which would otherwise be invoked with a fairly useless this. If no methodNames are provided, all of the object's function properties will be bound to it.
var buttonView = { label : 'underscore', onClick : function(){ alert('clicked: ' + this.label); }, onHover : function(){ console.log('hovering: ' + this.label); } }; _.bindAll(buttonView); jQuery('#underscore_button').bind('click', buttonView.onClick); => When the button is clicked, this.label will have the correct value...
If you can help out here by giving another example perhaps or some verbal explanation, anything would be appreciated. I tried to search for more tutorials or examples, but nil turn up that serve what I needed. Most people seem to just know what it does automatically...
Solution 1:
var Cow = function(name) {
this.name = name;
}
Cow.prototype.moo = function() {
document.getElementById('output').innerHTML += this.name + ' moos' + '<br>';
}
var cow1 = new Cow('alice');
var cow2 = new Cow('bob');
cow1.moo(); // alice moos
cow2.moo(); // bob moos
var func = cow1.moo;
func(); // not what you expect since the function is called with this===window
_.bindAll(cow1, 'moo');
func = cow1.moo;
func(); // alice moos
<div id="output" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
Unfortunately the actual "bind all" functionality only works on functions right on the object. To include a function that is defined on the prototype you need to pass those function names explicitely as additional arguments to _.bindAll()
.
Anyway, you wanted an explanation: Basically it allows you to replace a function on an object with a function that has the same name and behaviour, but is also bound to that object, so this === theObject
even without calling it as a method (theObject.method()
).
Solution 2:
The simplest explanation as for me is the next:
initialize:function () { //backbone initialize function
this.model.on("change",this.render); //doesn't work because of the wrong context - in such a way we are searching for a render method in the window object
this.model.on("change",this.render,this); //works fine
//or
_.bindAll(this,'render');
this.model.on("change",this.render); //now works fine
//after _.bindAll we can use short callback names in model event bindings
}