2 comments

[ 0.19 ms ] story [ 14.3 ms ] thread
While the advice is good it ends with some extremely dangerous assumptions about what [View].remove() actually does:

    "Calling remove() on a Backbone.View does several things:
    
    Remove Javascript events (click, keypress, blur, ...)
    Unbind all events of the model (change, sync, remove)
    Remove the element from the DOM"
But if you look at the code for Backbone.View.remove():

    remove: function() {
      this.$el.remove();
      return this;
    },
It removes the $el from the DOM. jQuery's function will automagically go ahead and remove any event listeners attached to $el or it's children. Zepto's remove() does not.

But the most dangerous assumption the author made is that it will unbind events from the model. It does nothing of the sort - you need to manually override remove() in your views to detach any event listeners on models/collections/views/routers. If you don't do this, the views will still exist in memory, consider the following:

    var Model = new Backbone.Model();
    var View = new (Backbone.View.extend({
        initialize: function () {
            Model.on("change", this.render, this);
        }
    })();
    View.remove();
    console.log(Model._callbacks);
If you dig into the Model._callbacks object you'll eventually find the View instance, still referenced (and so still in memory). The simple way to fix this would be to add this remove function to the view:

    remove: function () {
        Model.off(this);
        return Backbone.View.prototype.remove.call(this);
    }
I don't understand. How is it dangerous? Dangling Views that can't execute (call back) are a small heap leak. What else?