need explanation of the _.bindAll() function from Underscore.js
Javascriptbackbone.jsunderscore.jsJavascript Problem Overview
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...
Javascript Solutions
Solution 1 - Javascript
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 - Javascript
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
}
Solution 3 - Javascript
try this
<input type="button" value="submit" id="underscore_button"/>
<script>
var buttonView = {
id : 'underscore',
onClick: function () {console.log('clicked: ' + this.id)},
onHover: function () {console.log('hovering: ' + this.id)}
}
_.bindAll(buttonView, 'onClick')
$('#underscore_button').click(buttonView.onClick)
$('#underscore_button').hover(buttonView.onHover)
</script>