如何使用 Chrome 开发工具找出引用分离的 DOM 树的内容

Posted

技术标签:

【中文标题】如何使用 Chrome 开发工具找出引用分离的 DOM 树的内容【英文标题】:How to find out what is referencing a detached DOM tree using Chrome Dev Tools 【发布时间】:2013-07-19 11:39:11 【问题描述】:

我试图弄清楚如何准确地获取哪个变量引用了分离的 DOM 树中的某些内容。我已将问题隔离为两个简单的视图,我正在尝试使用 Chrome 开发工具(在比较视图中)找出引用分离节点的内容。我附上了一张开发工具的图片……

开发工具的底部显示HomeViewel 创建了一个分离的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。 泄漏触发行为是使用菜单在两个页面之间导航。

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

【问题讨论】:

尝试选择 [917] 对象并打开控制台 (Esc) 并评估 $0 我不知道您可以使用这样的开发工具进行评估 - 这真的很有用!谢谢!但是,当我选择“(全局句柄)”然后评估它时显示为“未定义”? Finding JS memory leak in chrome dev tools的可能重复 【参考方案1】:

Ug 咖啡脚本。

除此之外,每当您在页面上使用 jquery 进行内存泄漏搜索时,您都需要禁用 jquery dom 缓存。在我对您链接到的示例站点的简短操作中,我很确定我看到的一些分离节点在该缓存中。

$.expr.cacheLength = 1;

这是非常糟糕的记录,但应该可以帮助您找出实际泄漏的来源。

【讨论】:

以上是关于如何使用 Chrome 开发工具找出引用分离的 DOM 树的内容的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 开发工具可以帮助找出 Angular 组件名称吗?

Chrome 开发者工具:如何找出覆盖 CSS 规则的内容?

如何找出在 Chrome 开发工具中添加样式属性的位置?

文档 Dom 树与分离的 Dom 树?

如何将 chrome 开发者控制台停靠在左侧?

如何使用chrome浏览器进行js调试找出元素绑定的点击事件