In addition to jQuery, Backbone also requires one library called
Underscore. Underscore was written by Jeremy Ashkenas (the creator of Backbone), and many of its functions are relevant to the topics we've discussed so far. Because Underscore is required by Backbone, you'll already have it available to you if you use Backbone. All of these functions can be accessed via the _
character (similar to how jQuery functions are accessed via the $
character).
As we discussed the call
and apply
methods, you may have realized that this is more fluid in JavaScript than in other languages. While a function that is called normally will preserve the this
method automatically, when a function is called in an unusual way—such as through window.setTimeout
or as a callback to a jQuery event handler or AJAX call—that won't be the case. The window.setTimeout
will change this to the global window object, while jQuery event callbacks will change this
to the element that triggered the event and jQuery AJAX callbacks will set it to the HTTP request created by the AJAX call. Here's a quick example:
var exampleObject = {}; exampleObject.alertThis = function() { alert(this); }; window.setTimeout(exampleObject.alertThis); // alerts window
The solution to this problem is to use extra functions and use apply
to wrap the original function so that we can force JavaScript to preserve our this
method:
var exampleObject = {}; exampleObject.alertThisBuilder = function() { var alertThis = function() { alert(this); } var correctThis = this; return function() { alertThis.apply(correctThis); } }; var alertThis = exampleObject.alertThisBuilder(); window.setTimeout(alertThis); // alerts exampleObject
This works but let's face it: it's ugly. Luckily, Underscore has a two solution for this: bind
and bindAll
.
Let's start with bind
. The bind
functions allows you to force a function, which you provide as the first argument, to preserve a specific this
value, which you provide as the second argument:
var simpleBook = {}; simpleBook.alertThis = function() { alert(this); }; simpleBook.alertThis = _.bind(simpleBook.alertThis, simpleBook); window.setTimeout(simpleBook.alertThis); // now alerts simpleBook, not window
Underscore also has a related bindAll
function, which can be used to permanently bind
a method:
var Book = Backbone.Model.extend({ initialize: function() { _.bindAll(this, 'alertThis'), }, alertThis: function() { alert(this); } }); var book = new Book(); window.setTimeout(book.alertThis); // alerts book, not window
As you can see, bindAll
allows you to use your class's methods with setTimeout
or as callbacks to jQuery event handlers or AJAX operations, without losing this
.
While bindAll
is very powerful, it is important not to overuse it, because it creates a new copy of every method it binds. If used inside a class, this will result in every instance of that class to have its own separate copy of that method. While this is perfectly fine when you only have a few bound methods and/or only a few instances, you will not want to use it on a large number of methods with a class that will be instantiated many times.
18.191.202.174