如何销毁一个JavaScript对象?

89

最近,我发现我的一个应用程序消耗了太多的内存,并且每秒增加10 MB。

因此,我想知道如何销毁JavaScript对象和变量,以使内存使用保持在较低水平,避免Firefox被破坏。

我每8秒调用两个脚本而不重新加载页面。

function refresh() {
    $('#table_info').remove();
    $('#table').hide();
    if (refreshTimer) {
        clearTimeout(refreshTimer);
        refreshTimer = null ;
    }
    document.getElementById('refresh_topology').disabled=true; 
    $('<div id="preload_xml"></div>').html('<img src="pic/dataload.gif" alt="loading data" /><h3>Loading Data...</h3>').prependTo($("#td_123"));
    $("#topo").hide();
    $('#root').remove();
    show_topology();
}

我怎样才能知道是哪个变量导致内存超载,并停止该进程的执行?


2
你有没有考虑使用闭包来隔离你的代码部分? - YS.
2
你尝试过什么吗?比如使用 obj = null 吗? - Florian Margaine
A) show_topology 函数是做什么的? --- B) 你是否会清除添加到 #td_123 的内容?--- C) 这个项目有实时版本吗? - Deestan
5个回答

105

您可以像这样将所有代码放在一个命名空间下:

var namespace = {};

namespace.someClassObj = {};

delete namespace.someClassObj;

使用delete关键字会删除属性的引用,但在低层次上,JavaScript垃圾回收器(GC)将获取更多关于应该被回收的对象的信息。

您还可以使用Chrome开发者工具来获取应用程序的内存配置文件,并确定哪些对象需要缩小。


13
按下 F12 键打开开发者工具,切换到“Profile”选项卡并点击“Start”按钮开始性能分析。您可以进行 JavaScript CPU、CSS 选择器和堆快照的分析。 - Sarath
3
或者在最新版本的Chrome浏览器中,在JS控制台中输入“performance”一词。 - David Morrow
或许这很显然,但你可以将你的命名空间命名为“g”,从而节省大量的打字。使用g.curItem=...代替var curItem=...,既可以节省打字,也可以允许g=undefined来清除所有全局内存分配。 - David Spector

33

当没有任何引用指向对象时,该对象将被删除。你可以使用 delete 删除引用。

但是,如果你的对象中存在循环引用,则可能需要解除某些关系。


2
你能否添加一个循环引用的例子,这个例子不会被垃圾回收器捕获吗?为朋友打听一下!;) - Emil Hemdal
1
@emilhem,你可以引用垃圾回收器,它会自我删除和互联网 - 内部崩溃可能会在CERN创建黑洞。你有考虑过这个例子吗? - El Mac
@EmilHemdal V8使用两个标记-压缩垃圾收集器,这意味着即使您创建了循环引用,如果它无法从全局(或旧对象,但这只能让它在两次收集中存活)到达,它最终也会被收集。 - PoolloverNathan

30
虽然现有答案已经给出了解决问题和第二个问题的解决方案,但它们并没有回答加粗的第一个问题中关于自我发现方面的答案: "如何查看哪个变量导致内存开销...?"。三年前可能还不够强大,但Chrome开发者工具“Profiles”部分现在已经非常强大且功能丰富。Chrome团队在这篇深入的文章中介绍了如何使用它以及javascript垃圾回收(GC)的工作原理,这是本问题的核心。由于delete基本上是Yochai Akoka目前接受的答案的根源,因此需要记住delete的作用。如果没有与下面两个答案中GC工作原理相关的概念,则无关紧要:如果存在一个对对象的引用,它不会被清除。虽然这些答案更正确,但可能没有被重视,因为它们需要比仅仅写`delete`更多的思考。是的,一种可能的解决方案可以使用delete,但如果存在内存泄漏的另一个引用,那么它无关紧要。 另一个答案恰当地提到了循环引用,Chrome团队的文档可以提供更多的清晰度以及验证原因的工具。由于在这里提到了delete,因此提供资源《理解Delete》也可能有用。虽然它没有涉及任何实际解决方案,但与javascript的垃圾收集器相关。

9

将代码结构化,使所有临时对象都位于闭包内部而不是全局命名空间/全局对象属性中,并在使用完后退出作用域。垃圾收集器会处理剩下的事情。


1

我遇到了类似的问题,想到了简单地更改有问题对象的子元素的innerHTML。

adiv.innerHTML = "<div...> the original html that js uses </div>";

看起来很脏,但它救了我的命,因为它有效!


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