如何使用Chrome开发者工具查找引用分离的DOM树?

12

我正在尝试找出如何获取引用分离DOM树中的哪个变量。我已经将问题隔离到两个简单的视图,并且正在使用Chrome Dev Tools(在比较视图中)查找是什么引用了分离的节点。我已经附上了Dev工具的图像...

Chrome dev tools快照

Dev工具的底部显示,HomeViewel创建了一个已经被分离的div。但我不确定下一步该怎么做。

我已经阅读了许多关于定位内存泄漏的Stack Overflow帖子和博客文章,但仍然无法解决这个问题。我知道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);

...然后我在我的路由器的一个方法中调用每个视图的 "close" 方法...

  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

触发泄漏的行为是使用菜单在两个页面之间导航。

任何帮助将不胜感激!谢谢!


2
尝试选择[917]对象并打开控制台(Esc),然后评估$0 - Paul Irish
我不知道你可以像那样使用开发工具进行评估 - 这真的很有用!谢谢!但是,当我选择“(Global handles)”然后评估时,它变成了“未定义”? - Jacquerie
可能是在Chrome开发工具中查找JS内存泄漏的重复问题。 - Paul Sweatte
1个回答

5

使用CoffeeScript编写代码。

另外,当您在页面上使用jQuery进行内存泄漏调试时,需要禁用jQuery DOM缓存。在我简短地尝试了您提供的示例站点后,我几乎确定我看到的一些分离节点位于该缓存中。

$.expr.cacheLength = 1;

这个文档记录得非常不好,但应该能帮助你找出实际内存泄漏的来源。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接