2

编辑:在进一步检查中,Firefox 似乎没有这样做,但 Chrome 肯定会这样做。我猜这只是新浏览器的一个错误 - 对于每个事件,I/O 读取也会发生在 Chrome 中,但不会发生在 FF 中。

当我在浏览器中加载以下页面时(我在 Vista 下的 Chrome 和 Firefox 3 中进行了测试)并在周围移动鼠标时,内存总是增加并且似乎永远不会减少。

这是:

  1. 浏览器的预期行为
  2. 浏览器中的内存泄漏或
  3. 提供的代码中的内存泄漏?

.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>test</title>
</head>
<body>
   <script>
      var createEl = function (i) {
          var el = document.createElement("div");
          var t = document.createTextNode(i.toString());
          el.appendChild(t);
          t=null;
          el.id=i.toString();

          var fn = function (e) {};
          el.addEventListener("mouseover", fn, false);
          //el.onmouseover = fn;
          fn = null;

          try{
            return el;
          }
          finally{
            el=null;
          }
          //return (el = [el]).pop();
        };

        var i,x;
        for (i= 0; i < 100; i++){
          x = createEl(i)
          document.body.appendChild(x);
          x = null;
        }
   </script>
</body>
</html>

和想法都来自这里(el = [el].pop()),尽管它们似乎都没有帮助 - 可以理解,因为它们只是用于 ie6 修复。try/finally

我还尝试过使用 addEventListener 和 onmouseover 方法来添加事件。我发现防止内存增加的唯一方法是注释掉这两行代码。

4

3 回答 3

2

fn 是一个闭包,即使其中没​​有代码。例如,尝试使用 Firebug 进行调试并在该函数内设置断点。闭包中定义的所有变量(fn 代码 + 挂起的变量 = 闭包)理论上都是可访问的(尽管我不知道如何在实践中访问它们)。

于 2010-12-17T12:24:40.000 回答
1

好吧,这根本不是我处理这个问题方式,而且我无法复制这种行为,所以我只能告诉你,你在记忆方面遇到的问题很可能是因为fn函数中的任何内容,除非它是您应该fn在函数外部定义闭包,createEl并仅在函数内部引用它,因此内存中只存在一个实例。

不过,您需要更好地处理事件绑定(这不是 xbrowser 安全的 - 在这一点上我犹豫是否建议使用 jQuery),而且整个(el =[el]).pop()巫毒教的恶臭对我来说都很糟糕,尽管如果有人能准确地解释什么,我很高兴得到纠正它实现了。

于 2009-01-29T13:26:08.113 回答
1

与事件处理程序相关的内存泄漏通常与外壳有关。换句话说,将函数附加到指向其元素的事件处理程序可以防止浏览器进行垃圾收集。(谢天谢地,大多数较新的浏览器已经“学会了诀窍”并且在这种情况下不再泄漏内存,但是有很多旧浏览器漂浮在那里!)

这样的外壳可能如下所示:

var el = document.createElement("div");
var fnOver = function(e) {
    el.innerHTML = "Mouse over!";
};
var fnOut = function(e) {
    el.innerHTML = "Mouse out.";
};

el.addEventListener("mouseover", fnOver, false);
el.addEventListener("mouseout", fnOut, false);

document.getElementsByTagName("body")[0].appendChild(el);

事实上,fnOverfnOut触及它们的封闭范围以引用el是创建一个封闭(实际上是两个 - 每个功能一个)并可能导致浏览器泄漏的原因。您的代码不会做这样的事情,因此不会创建任何外壳,因此不应导致(行为良好的)浏览器泄漏。

我猜这只是测试版软件的一大败笔。:-)

于 2009-01-29T15:52:44.730 回答