【问题标题】:javascript - is that a memory leak?javascript - 这是内存泄漏吗?
【发布时间】:2016-05-08 15:36:56
【问题描述】:

我的情况不完全是这样,但概念非常相似,我有一个通过 ajax 加载的内容,里面有一个脚本。

page1.html:

<div id="ajax-content"></div>
<button onclick="loadContent()">do ajax</button>
<script>
function loadContent() {
  $.get('page2.html', function(response) {
      $("#ajax-content").html(response);
  });
}  
</script>

page2.html:

<button id="btn">button</button>
<script>
(function() {
  var MyModule = {
      main: function() {
        $("#btn").click(function(){ 
            alert("btn click"); 
            // some code
        });
      }
      // some more functions...
  };    
  MyModule.main();
})();
</script>

假设“do ajax”按钮将被多次点击。
【每次点击都会从服务器加载内容,我想经常刷新。 ]
加载的页面 (page2.html) 中有一些交互式小部件,因此脚本标签会在那里加载和执行。
如您所见,我将 page2 中的所有代码放在一个自调用函数(模块模式)中,因为我不想污染全局范围。
由于每个 ajax 请求都导致再次调用脚本,MyModule 被多次创建,我不确定之前的副本是否会被 GC'ed。
所以在这里我想到了这是如何发生的,如果我错了,请告诉我-

  1. 按下“do ajax”按钮(page1.html),函数加载page2.html的内容,并将结果放入div中。
  2. 自调用函数得到执行,创建 MyModule。我的模块中的 main 函数被调用
  3. main 函数将事件处理程序绑定到 id='btn' 的按钮。 所以现在我们有这些参考: btn -> 处理程序 -> 所有自调用函数范围。

现在我不确定:如果我从文档中删除 id='btn' 的按钮,它的处理程序可以被 GC'ed => 整个自调用函数范围将被 GC 处理?
如果我是正确的,由于每个 ajax 调用都会替换 div[id='ajax-content'] 的 html,因此不会发生内存泄漏。

【问题讨论】:

  • 对于您的简单示例,这应该是正确的。这对你来说也很有趣:Do closures keep the whole execution context alive?
  • 我刚刚点击了您的链接,并得到了带有“JS/downloader”特洛伊木马的防病毒弹出窗口。任何解释为什么?
  • 它只是一个简单的链接,所以不,我无法想象为什么。

标签: javascript jquery html ajax memory-leaks


【解决方案1】:

TL;DR:在理想的浏览器实现中,您不应该有内存泄漏。

匿名函数声明和调用

(function() { ... })();

,如果单独使用,则创建 Function 对象并执行它。只要它不会对其内部范围对象进行任何引用,它将在下一次 GC 迭代时从堆中完全清除。

但在您的情况下,您有 $("#btn").click(function(){...}) - 单个引用,它将包含脚本的内部范围对象。因此,在#btn DOM 元素存在之前,这些对象将被 DOM 钩住。

如果您将删除 #btn 并删除 &lt;script&gt; DOM 元素本身,那么 GC 将能够完全清理您的动态脚本。

只是不要将此类临时对象的引用放入全局集合中(WeakMap 可以)。如果不对此类集合进行适当维护(例如删除未使用的),您可能会观察到类似的内存泄漏症状。

【讨论】:

    猜你喜欢
    • 2015-05-04
    • 2011-02-20
    • 2013-08-12
    • 2013-01-08
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多