3

以下 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 任务管理器中的内存不断增加。我预计当垃圾收集开始时内存会减少,但这似乎永远不会发生。

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

4

2 回答 2

2

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

于 2012-06-23T10:28:25.237 回答
0

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

除了一些有用的注释:使用闭包来封装来自窗口对象的代码。使用对文档的本地引用来避免范围链演练,使用一个片段来附加所有新的 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>

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

于 2012-06-23T11:44:25.730 回答