Как узнать, что относится к отдельному дереву DOM с помощью инструментов Chrome Dev

Я пытаюсь выяснить, как получить, какая переменная ссылается на что-то в отдельном дереве DOM. Я выделил проблему до двух простых видов, и я пытаюсь использовать Chrome Dev Tools (в представлении сравнения), чтобы узнать, что относится к отдельным узлам. Я прикрепил образ инструментов dev...

Chrome dev tools snapshot

Нижняя часть инструментов dev показывает, что el of HomeView создал div, который стал отсоединенным. Но я не уверен, куда идти оттуда.

Я прочитал кучу столбцов и сообщений в блоге о том, что я обнаружил утечки памяти, но я все еще не могу понять этого. Я знаю, что Backbone, в частности, может вызвать утечку памяти, поэтому я применил методы "зомби-убийства", но утечка памяти все еще существует. Вот мои взгляды:

Вид справки

    // Generated by CoffeeScript 1.6.3
    (function() {
      var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

      define(['jquery', 'jquerymobile', 'underscore', 'backbone'], function($, Mobile, _, Backbone) {
        var HelpView, _ref;
        return HelpView = (function(_super) {
          __extends(HelpView, _super);

          function HelpView() {
            _ref = HelpView.__super__.constructor.apply(this, arguments);
            return _ref;
          }

          HelpView.prototype.initialize = function() {
            return _.bindAll(this, "render", "jqdisplay", "close");
          };

          HelpView.prototype.render = function() {
            $(this.el).html("Help View");
            return this;
          };

          HelpView.prototype.jqdisplay = function() {};

          HelpView.prototype.close = function() {
            console.log('THIS', this);
            console.log($(this.el)[0].parentNode);
            $(this.el)[0].parentNode.removeChild($(this.el)[0]);
            this.undelegateEvents();
            $(this.el).removeData().unbind();
            this.remove();
            this.unbind();
            Backbone.View.prototype.remove.call(this);
            return delete this;
          };

          return HelpView;

        })(Backbone.View);
      });

    }).call(this);

Домашний просмотр

    // Generated by CoffeeScript 1.6.3
    (function() {
      var __hasProp = {}.hasOwnProperty,
        __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

      define(['jquery', 'jquerymobile', 'underscore', 'backbone'], function($, Mobile, _, Backbone) {
        var HomeView, _ref;
        return HomeView = (function(_super) {
          __extends(HomeView, _super);

          function HomeView() {
            _ref = HomeView.__super__.constructor.apply(this, arguments);
            return _ref;
          }

          HomeView.prototype.initialize = function() {
            return _.bindAll(this, "render", "jqdisplay", "close");
          };

          HomeView.prototype.render = function() {
            $(this.el).html("Home View");
            return this;
          };

          HomeView.prototype.jqdisplay = function() {};

          HomeView.prototype.close = function() {
            console.log('THIS', this);
            console.log($(this.el)[0].parentNode);
            $(this.el)[0].parentNode.removeChild($(this.el)[0]);
            this.undelegateEvents();
            $(this.el).removeData().unbind();
            this.remove();
            this.unbind();
            Backbone.View.prototype.remove.call(this);
            return delete this;
          };

          return HomeView;

        })(Backbone.View);
      });

    }).call(this);

... и затем я вызываю метод "закрыть" каждого представления в методе моего маршрутизатора...

  MyRouter.prototype.showView = function(view) {
    console.log('THIS', this);
    console.log("next view", view);
    console.log(this.currentView);
    if (this.currentView) {
      console.log('closing the current view...', this.currentView);
      console.log('starting', $('[data-role="content"]').html());
      this.currentView.close();
      delete this.currentView;
      console.log('remaining', $('[data-role="content"]').html());
      console.log('should be empty', this.currentView);
    }
    this.currentView = view;
    this.currentView.render();
    $('[data-role="content"]').html(this.currentView.el);
    if (this.currentView.jqdisplay) {
      return this.currentView.jqdisplay();
    }
  };

Ниже приведена живая демонстрация утечки: http://bit.ly/15xPrW7. Поведение запуска утечки использует меню для перемещения между двумя страницами.

Любая помощь будет оценена! Спасибо!

Ответ 1

Ug coffeescript.

В стороне, в любое время, когда вы пытаетесь найти утечку памяти с jquery на странице, вам нужно отключить кеш jquery dom. В моей короткой игре с примером сайта, с которым вы связались, я уверен, что некоторые из отдельных узлов, которые я вижу, находятся в этом кеше.

$.expr.cacheLength = 1;

Это очень плохо документировано, но должно помочь вам выследить, откуда происходят ваши фактические утечки.