如何销毁JavaScript对象?


81

最近,我遇到了我的一个应用程序,该应用程序占用太多内存,并且以10 MB /秒的速度增长。

因此,我想知道销毁JavaScript对象和变量的最佳方法,这样可以减少内存消耗,并且不会销毁我的FF。

我每8秒钟间隔调用两个JavaScript,而无需重新加载页面。

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();
}

如何查看哪个变量导致内存开销和方法停止执行该进程?


1
您是否考虑过使用闭包来隔离部分代码?
YS。

1
你有尝试过吗?喜欢使用obj = null吗?
Florian Margaine '04年

A)怎么show_topology办?--- B)您是否曾经清理过要添加的内容#td_123?--- C)某处有现场版本吗?
Deestan

Answers:


93

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

var namespace = {};

namespace.someClassObj = {};

delete namespace.someClassObj;

使用delete关键字将删除对该属性的引用,但是在较低级别,JavaScript垃圾收集器(GC)将获得有关要回收哪些对象的更多信息。

您还可以使用Chrome开发者工具获取应用的内存配置文件,以及应用中需要缩小的对象。


12
按F12获取开发人员工具。转到配置文件选项卡,然后单击开始以启动配置文件。您可以在JS CPU,CSS选择器上进行性能分析,并可以获取堆快照。
Sarath 2012年

3
或使用最新的Chrome键入js控制台中的“性能”一词
David Morrow 2013年

也许这很明显,但是您可以将名称空间命名为“ g”,并节省大量输入。使用g.curItem = ...而不是var curItem = ...,保存类型以及允许g = undefined清除所有全局内存分配。
David Spector

31

您无法删除对象,如果没有更多引用,它们将被删除。您可以使用删除参考delete

但是,如果您在对象中创建了循环引用,则可能必须取消某些操作的耦合。


2
您能否添加一个垃圾收集器不会捕获的循环引用示例?要求朋友!;)
emilhem

@emilhem您可以引用垃圾收集器,它将删除自身和互联网-内爆可能会在CERN造成一个黑洞。您是否考虑过该示例?
El Mac

28

尽管现有答案给出了解决问题和问题后半部分的解决方案,但它们并未以粗体显示问题上半部分的自我发现方面的答案:

“如何查看哪个变量导致内存开销……?”

它可能在3年前还没有那么强大,但是Chrome开发者工具的“配置文件”部分现在功能强大且功能丰富。Chrome小组有一篇很有用的文章,介绍了如何使用它,以及垃圾收集(GC)如何在javascript中工作,这是此问题的核心。

由于delete基本上是Yochai Akoka当前接受的答案的根源,因此记住删除功能很重要。如果不与以下两个答案中GC如何工作的概念结合起来,这是不相关的:如果存在对对象的现有引用,则不会对其进行清理。答案更正确,但可能不那么受欢迎,因为答案需要更多思考,而不仅仅是写“删除”。是的,一种可能的解决方案可能是使用delete,但是是否还有其他引用涉及内存泄漏也没关系。

另一个答案适当地提到了循环引用,Chrome团队文档可以提供更高的清晰度以及用于查明原因的工具。

由于delete此处已提及,因此提供资源谅解删除可能也很有用。虽然它并没有进入任何实际的解决方案,它是真正关系到JavaScript的垃圾收集器。


9

对代码进行结构化,以便所有临时对象都位于闭包中,而不是全局名称空间/全局对象属性中,并且在使用完它们后就超出范围。GC将负责其余的工作。


1

我当时遇到了这样的问题,并且想到了只更改有问题的对象的子代的innerHTML的想法。

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

看起来很脏,但它挽救了我的生命,因为它起作用了!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.