这个简单的js代码是否有内存泄漏?

时间:2013-03-09 15:39:28

标签: javascript memory-leaks

我有一个简单的html / javascript代码,它会创建一些DOM,然后删除它们。

<!DOCTYPE html>
<html>

  <head lang="en">
    <meta charset="utf-8">
    <title>Custom Plunker</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
  </head>

  <body>
    <button onclick="create()"> Create </button>
    <button onclick="clearContainer()"> Clear </button>

    <div id="container"></div>

  </body>

</html>

<script>
  function create() {
    var c = $("#container");
    for(var i = 0;i<10000; i++){
    c.append("<li>Hellosd fssd f df sdf  f f wef ewf we fwe f wef ewf wef ew few f ewf wf ewf wef </li>");
    }
  }

  function clearContainer() {
    var c = $("#container");
    c.empty();
  }
</script>

会有Create按钮和Clear按钮。当我单击创建按钮时,它会将10000 li元素附加到容器div,当我单击清除按钮时,它将删除它们。

当我在chrome上试用它时,chrome进程的初始内存使用量大约为30M,在我点击创建按钮几次后它增长到70M,当我点击clear按钮时,它变为50M。它比初始时多20M。

然后我在IE8上尝试,IE进程的初始内存使用量大约为30M,单击“创建”按钮一次后,它增长到100M以上,当我点击“清除”按钮时,它变为80M。它比初始值高出50M。

代码是否有内存泄漏?如何解决?

2 个答案:

答案 0 :(得分:7)

  

代码是否有内存泄漏?

没有。浏览器只是保留它们分配的一些内存,以防它们需要重用它,和/或还没有(还)垃圾收集不再引用的对象。因为你已经发布了对列表项元素的所有引用(通过jQuery的empty调用),所以它是由浏览器实际让它们去的。

当然,这个答案假设您正在调用的jQuery函数中没有错误导致内存泄漏(特别是创建li元素的那个)。这可能是一个合理的假设,虽然当然每隔一段时间,即使是一个备受尊重的图书馆也会有错误。如果jQuery的一个常见功能(包括元素构造)在给定版本中具有显着的内存泄漏,则可能会在合理的时间内找到,报告和修复,因为使用该库的人数和所涉及的团队它

我们还假设浏览器处理导致内存泄漏的DOM操作没有错误,这是一个不太确定的假设。 (从历史上看,浏览器[无论风味如何]都存在内存泄漏的各种问题;我认为任何浏览器都不具备免疫力。)

但如果您明白我的意思, 代码中没有泄漏。

答案 1 :(得分:4)

通过在Chromium / linux上测试,我可靠地重现你的泄漏:每个创建/清除周期使内存增长5MB到10 MB,并且这个内存似乎没有被释放。

我注意到可以通过稍微更改clear函数来替换父元素而不是清空它来避免泄漏:

  function clearContainer() {
    var c = $("#container");
    c.remove();
    $('<ul id="container"></ul>').appendTo(document.body);
  }

使用此代码,每次创建/清除循环后内存都会回到同一级别。

我认为问题不在jQuery中,但更可能在浏览器的DOM对象中,因为Firefox似乎没有同样的问题。


编辑

通过自动化测试将其推得更远,我可以看到内存最终减少(我为标签增加了大约150 MB然后可以回到70 MB)。这里管理内存的方式显然是贪婪的,但没有真正的内存泄漏。由于内存消耗可能会有所不同,我建议您删除父元素而不是清除它,但这不会阻止任何崩溃,因为内存崩溃似乎不太可能。