我可以触发JavaScript垃圾回收吗?

时间:2011-11-07 05:05:53

标签: javascript garbage-collection

我想触发JavaScript垃圾回收。可能吗?我为什么要或不想这样做?

9 个答案:

答案 0 :(得分:42)

我出去了一个小小的旅程,寻求你的一个问题的答案:有可能吗?

全镇各地的人都说删除参考文献就可以了。有人说擦拭物体是一种额外的保证(example)。所以我写了一个脚本,将尝试书中的每一个技巧,我很惊讶地看到在Chrome(22.0.1229.79)和IE(9.0.8112.16421),垃圾收集似乎甚至没有工作。 Firefox(15.0.1)管理没有任何重大缺点(见下面的案例4f)。

在伪代码中,测试就是这样的。

  1. 创建一个容器,一个数组,它将保存某种对象。我们将在此处调用此容器Bertil

  2. 其中的每一个对象,作为Bertil中的一个元素,都应该将自己的数组容器声明为属性。这个数组将包含很多字节。我们将调用Bertil的任何一个元素,对象Joshua。每个Joshua的字节数组都将被称为Smith

    这是您可以依靠的思维导图:

    Bertil [对象数组] - > Joshua [对象] - > Smith [字节数组] - >未命名[字节]。

  3. 当我们从可用内存中弄得一团糟时,请暂停一两秒,然后执行以下任何一种“破坏算法”:

    4A。在主对象容器Bertil上抛出一个删除操作数。

    4b中。在该容器中的每个对象上抛出一个删除操作数,杀死每一个活着的Joshua。

    4c中。在每个字节数组(Smiths。)上抛出一个删除操作数。

    4d上。为每个Joshua分配NULL。

    4e中。将UNDEFINED分配给每一个约书亚。

    的4f。手动删除任何约书亚所持的每个字节。

    4克。完成上述所有工作。

  4. 那么发生了什么?如果 4a 4b ,则没有浏览器的垃圾收集器(GC)启动。如果 4c到4e ,Firefox确实开始并展示了一些概念证明。记忆在一分钟之内就被收回了。对于用作测试配置的某些变量的当前硬编码默认值,案例 4f 4e 导致Chrome挂起,因此我无法得出任何结论。您可以使用自己的变量自由进行测试,链接将很快发布。 IE幸存下来的案例4f和4e,但他的GC像往常一样死了。出乎意料的是,Firefox幸免于难,但未通过4f。 Firefox幸存并传递了4g。

    在浏览器的GC无法启动的所有情况下,等待至少10分钟并没有解决问题。并且重新加载整个页面导致内存占用量增加一倍。

    我的结论是,我必须在代码中犯了一个可怕的错误,或者你的问题的答案是:不,我们不能触发GC。每当我们试图这样做时,我们将受到严厉的惩罚,我们应该把头埋在沙子里。我鼓励您继续,自己尝试这些测试用例。看看代码中的详细评论。此外,下载页面并重写脚本,看看是否可以更恰当的方式触发GC。我确实失败了,我不能相信Chrome和IE的生活中没有垃圾收集器。

      

    http://martinandersson.com/dev/gc_test/?case=1

         

    http://martinandersson.com/dev/gc_test/?case=2

         

    http://martinandersson.com/dev/gc_test/?case=3

         

    http://martinandersson.com/dev/gc_test/?case=4

         

    http://martinandersson.com/dev/gc_test/?case=5

         

    http://martinandersson.com/dev/gc_test/?case=6

         

    http://martinandersson.com/dev/gc_test/?case=7

答案 1 :(得分:7)

你可以在IE和Opera中手动触发JavaScript垃圾收集器,但不建议这样做,所以最好不要使用它。我提供更多命令只是为了提供信息。

Internet Explorer:

window.CollectGarbage()

Opera 7 +:

window.opera.collect()

答案 2 :(得分:6)

垃圾收集自动运行。如何以及何时运行并实际释放未引用的对象完全是特定于实现的。

如果你想要释放某些东西,你只需要从你的javascript清除对它的任何引用。然后垃圾收集器将释放它。

据我所知,没有办法手动触发垃圾收集。

如果你解释为什么你甚至认为你需要这样做或想要这样做并向我们展示相关的代码,我们可以帮助解释你的替代品。

答案 3 :(得分:3)

  1. 检查代码中的全局变量。可能存在通过存储的ajax调用传入的数据,然后在某处引用并且您没有考虑到这一点。
  2. 作为一种解决方案,您应该将大量数据处理包装到匿名函数调用中,并在此调用中仅使用局部变量来防止引用全局范围内的数据。
  3. 或者您可以将所有使用过的全局变量赋值为null。
  4. 同时查看this question。看看答案中的第三个例子。您的巨大数据对象仍可能被异步调用关闭引用。

答案 4 :(得分:2)

This answer为基于Gecko的浏览器建议了以下垃圾收集请求代码:

    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
      .getInterface(Components.interfaces.nsIDOMWindowUtils)
      .garbageCollect();        

答案 5 :(得分:1)

是的,您可以通过重新加载页面来触发垃圾收集。

您可能需要考虑使用工厂模式来帮助重复使用对象,这将大大减少创建的对象数量。特别是,如果您不断创建相同的对象。

如果您需要阅读工厂模式,那么请阅读Ross Harmes和Dustin Diaz撰写的“Pro Javascript Design Patterns”,并由APress出版。

答案 6 :(得分:1)

遇到这个问题并决定与我最近的调查结果分享。 我希望看到在Chrome中正确处理WeakMap,它实际上看起来还不错:

1)var wm = new WeakMap()

2)var d = document.createElement('div')

3)wm.set(d, {})

在这个阶段,弱映射保存条目,因为d仍然引用元素

4)d = null

在这个阶段没有引用元素,它是弱引用的对象,实际上在几分钟之后,条目消失并收集垃圾。

什么时候做了相同但是将元素附加到DOM,它没有被回收,这是正确的,从DOM中移除并仍在等待它被收集:)

答案 7 :(得分:1)

我正在阅读Trevor Prime的答案,它给了我一个轻笑,但后来我意识到他正在做些什么。

  1. 重新加载页面会进行垃圾收集'。
  2. location.reload()或刷新页面的替代方法。
  3. JSON.parse / stringify和localStorage.getItem / setItem,用于持久存储所需数据。
  4. iframes为用户体验重新加载页面。
  5. 您需要做的就是在iframe中运行代码并刷新iframe页面,同时将有用信息保存到localStorage中。您必须确保iframe与主页位于同一个域中才能访问其DOM。

    你可以在没有iframe的情况下做到这一点,但用户体验无疑会受到影响,因为页面会明显重置。

答案 8 :(得分:0)

如果确实没有如其他答案所暗示的那样触发GC的方法,那么解决方案将是为适当的浏览器标准组添加一个新的JavaScript函数到窗口或文档中以执行此操作。允许网页在自己选择的时间触发GC很有用,这样动画和其他高优先级操作(声音输出?)将不会被GC中断。

这可能是“我们一直以这种方式做到;不要动摇”综合征的另一种情况。

已添加:

MDN记录了一个函数“ Components.utils.schedulePreciseGC”,该函数使页面可以在将来某个时候通过GC完成时调用的回调函数来调度GC。 Firefox以外的其他浏览器可能不存在此功能;文档不清楚。此功能可能在动画之前可用。它需要测试。