【问题标题】:Javascript removeChild memory leak?Javascript removeChild内存泄漏?
【发布时间】:2012-06-23 10:18:03
【问题描述】:

以下 javascript 代码似乎泄漏了内存,但我不知道为什么。我已经在 chrome 19 和 firefox 12 中尝试过。代码如下:

<body>
    <input id="add" type="button" value="add" onclick="add()" />
    <input id="remove" type="button" value="remove" onclick="remove()" />
    <div id="content">
    </div>
</body>

<script>
    var count = 0;

    function add() {
        var i = 0,
            newdiv;

        for (i = 0; i < 10000; i++) {
            newdiv = document.createElement('div');
            document.getElementById("content").appendChild(newdiv);
            newdiv.setAttribute('id', "div" + count);
            newdiv.innerHTML = "section " + count;
            newdiv = null;

            count = count + 1;
        }
    }

    function remove() {
        var i = 0;
        for (i = 0; i < count; i++) {
            document.getElementById("content").removeChild(document.getElementById("div" + i));
        }
        count = 0;
    }

</script>

当您不断单击添加 按钮,然后单击删除 按钮时,Windows 任务管理器 中的内存会不断增加。我预计当垃圾收集开始时内存会减少,但这似乎永远不会发生。

所以,我的问题是:这段代码是否存在内存泄漏?如果是,我该如何重构代码以修复泄漏?

【问题讨论】:

  • 它似乎在 Chromium 19/Ubuntu 11.04 中没有内存问题。
  • 只有一两个假设:newdiv = null; 不等于 delete newdiv; 所以我可能认为删除比将一些设置为 null 更好,这实际上不是 undefined...如果你使用本地存储的文档引用并在闭包中执行所有内容,而不是在全局窗口对象上创建东西甚至会加速这件事并减少内存使用恕我直言

标签: javascript memory-leaks


【解决方案1】:

我已经用 Chrome 19.0 对此进行了测试,是的,你是对的,内存增加了。但大约 30 秒后,垃圾收集开始并恢复正常。

【讨论】:

    【解决方案2】:

    我不能真正证明存在内存泄漏......但想象一下,你想在一场精彩的体育比赛后清理 10000 个瓶子,需要一些时间和资源;)

    除了一些有用的 cmets:使用闭包来封装来自窗口对象的代码。使用对文档的本地引用来避免范围链演练,使用一个片段来附加所有新的 div,而不是每次都访问文档,避免函数开销(这些都只是建议,不一定是您正在寻找的东西,但无论如何都是好的东西并且至少应该减少一点问题:)

    注意:这些示例可能无法完全跨浏览器运行

    <body>
      <input id="add" type="button" value="add">
      <input id="remove" type="button" value="remove">
      <div id="content"></div>
    </body>
    <script>
      (function(DOC) {
        var count = 0, getById = DOC.getElementById, createFragment = DOC.createDocumentFragment;
    
        getById("add").addEventListener("click", function() {
          var i = 0,
              newdiv,
              fragment = createFragment();
    
          for (; i < 10000; i++) {
            newdiv = document.createElement('div');
            newdiv.id = "div" + count;
            newdiv.innerHTML = "section " + count;
    
            fragment.appendChild(newdiv);
            delete newdiv;
          }
          getById("content").appendChild(fragment);
          count = i;
        }, false);
    
        getById("remove").addEventListener("click", function() {
          var element, i = 0;
          for (; i < count; i++) {
            element = getById("div" + i);
            element.parentNode.removeChild(element);
          }
          count = 0;
        }, false);
    
      })(document);
    </script>
    

    我希望这有助于解决或至少减少泄漏。 =)

    【讨论】:

      猜你喜欢
      • 2016-03-25
      • 2011-02-28
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      • 2014-04-08
      • 2013-03-29
      相关资源
      最近更新 更多