I’m not a newbie to JavaScript, but often I find its flexible ways (like defining anonymous function as callbacks and their scope) quite confusing. One thing I’m still struggling with are closures and scopes.
Take this example (from a Backbone model):
'handleRemove': function() {
var thisModel = this;
this.view.$el.slideUp(400, function() { thisModel.view.remove(); });
},
After the model is removed/deleted, this will animate its view and finally remove it from the DOM. This works just fine – but initially I tried the following code:
'handleRemove': function() {
var thisModel = this;
this.view.$el.slideUp(400, thisModel.view.remove );
},
Which is basically the same, but without the function() {} wrapper for the remove() call.
Can someone explain why the latter code does not work? I get the following exception/backtrace:
Uncaught TypeError: Cannot call method 'remove' of undefined backbone-min.js:1272
_.extend.remove backbone-min.js:1272
jQuery.speed.opt.complete jquery-1.8.3.js:9154
jQuery.Callbacks.fire jquery-1.8.3.js:974
jQuery.Callbacks.self.fireWith jquery-1.8.3.js:1084
tick jquery-1.8.3.js:8653
jQuery.fx.tick
Thank you!
That’s because the context (
this) of the callback function changes to the element being animated by jQuery.Furthermore, Backbone’s view.remove function looks like this (source code):
Because
thisis not the Backbone view object any more,$elis not defined. Hence you get the “Cannot call method ‘remove’ of undefined” error.Another way to avoid the error is to use Underscore’s
_.bindmethod: