【问题标题】:Javascript Freeing the DOMJavascript 释放 DOM
【发布时间】:2014-01-21 03:56:03
【问题描述】:

我编写了一个相当大的网络应用程序。它工作了一段时间,然后慢慢开始缓慢运行,因为 DOM 节点开始蠕动在 80,000 - 100,000 左右。

所以我一直在 Chrome 开发工具控制台 (DCTC) 中处理一些小数据集。

有人可以告诉我为什么以下内容有时有效,有时却无效。

var test = $('<div></div>');
test.remove();
test = null; //Doesn't seem to make a difference when it doesn't work

如果我在 CDT 的时间轴下查看 DOM 节点数,有时节点数会正确,有时它似乎拒绝放弃我试图删除的 DOM 节点。即使在按下 GC 按钮后也是如此。

以下在移除 DOM 节点和释放内存方面似乎是一致的。

//Seems to remove nodes just fine
for(var i = 0; i<100; i++){
    var test = $('<div></div>');
    $("body").append(test);
}
$("body").empty();

关于第一个示例,我认为它有时可能因为 NODELETE 标志而不起作用,因为它是一个变量定义,所以我尝试将我的赋值放在一个对象上,但这没有帮助。实际上,jQuery 的 remove 不会删除 dom 节点似乎更一致。

//Does not remove the node.
var test = {};
test.node = $('<div></div>');
test.node.remove();
test.node = null;

为什么不一致?

观察:

如果我这样做test = document.createElement('div');,它将始终创建一个分离的节点。 var test = .... 似乎始终如一地允许我清除节点,直到它搞砸然后所有赌注都关闭。

针对大家说没有 DOM 节点,请阅读以下内容:https://developers.google.com/chrome-developer-tools/docs/heap-profiling-dom-leaks 我要删除的 DOM 节点显示在分离的 dom 节点中,但“我该如何摆脱它们”是迫在眉睫的问题仍然存在。

【问题讨论】:

  • $('&lt;div&gt;&lt;/div&gt;') 创建一个新元素,在下一行删除它没有意义,因为它不在 DOM 中?
  • 您正在创建一个 div 并没有将它应用到任何地方,所以它不在 DOM 中。删除不会做任何事情
  • @adeneo 这很好,但是将变量设置为 null 也不会删除 DOM 节点。所以对它的任何引用都会丢失,GC 不会收集它。这是没有意义的。
  • 在你真正将它添加到 DOM 之前,没有什么可以删除的,它只是一个保存元素的变量,当将变量设置为 null 时,你希望删除哪个 DOM 节点?跨度>
  • 那么您是在告诉我 Chrome 开发工具的 DOM 计数报告不正确吗?如果您使用$('&lt;div&gt;&lt;/div&gt;'); 或使用document.createElement('&lt;div&gt;'); 创建一个元素,DOM 计数会上升,但永远不会下降。不管它是否被插入到页面中,Chrome 开发工具似乎都认为它们在某处徘徊。这是不正确的吗?我只希望我的 DOM 节点数减少 :)

标签: javascript google-chrome memory google-chrome-devtools


【解决方案1】:

经过更多测试,这是我想出的:

控制台确实正确显示了 DOM 节点数。然而,它似乎也错误地处理了变量声明和删除 DOM 节点。如果我从脚本运行我的示例,它们就可以正常工作,而不是从控制台运行。

如果我这样做:

        <script>
            var test = document.createElement('div');
            test = null;
            var test = {};
            test.node = document.createElement('div');
            delete test.node;


            var test = $('<div><div></div><div></div></div>');
            test.on("click", function(){
                alert('yes');
            });
            test.remove();
            test = null;
            //test = null;

            var test2 = {};
            test2.node = $('<div></div>');
            test2.node.remove();
            delete test2.node;
        </script>

从我的页面内部,它正确地释放了内存和孤立的 DOM 节点。如果我没有将变量设置为 NULL 或从对象中删除它,则分离的 DOM 节点将保留在那里并且无法删除它,因为您不再有对它的引用。

我认为对于那些使用 jQuery 并仅依赖 remove() 函数的人来说,这是一个很好的警告。

【讨论】:

  • 在使用 gc 调试/分析内存使用(对象分配)时需要小心。当您将对象设置为null 或对该属性调用delete 时,它不会立即从内存中删除。它可能会在内存中停留几个小时,如果引擎有足够的内存剩余,你会经常看到内存增长到某个阈值,然后在触发 gc 时迅速减少到某个阈值,以避免应用程序阻塞,有没有完全释放所有未使用的对象。
  • 是的,但是 Chrome 开发工具中有一个 GC 按钮,应该会立即触发 GC。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 2013-01-03
相关资源
最近更新 更多