Javascript事件处理程序总是增加浏览器内存使用量

时间:2009-01-29 13:06:54

标签: javascript memory-leaks event-handling

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

当我在浏览器中加载以下页面时(我已经在Chrome中测试了Firefox和Firefox 3)并且在内存中移动鼠标会一直增加并且似乎永远不会消退。

这是:

  1. 来自浏览器的预期行为
  2. 浏览器中的内存泄漏或
  3. 所呈现代码中的内存泄漏?
  4. <!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())try/finally提示均来自here,但它们似乎没有任何帮助 - 可以理解,因为它们只是为了修复它们。

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

3 个答案:

答案 0 :(得分:2)

即使没有代码,

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

答案 1 :(得分:1)

这不是我在所有处理这个的方式,而且我无法复制这个行为所以我能告诉你的是你有记忆的问题可能是因为fn函数中的任何内容,除非它是一个闭包,否则你应该在fn函数之外定义createEl并仅在其中引用它,因此在内存中只存在一个实例

你需要更好地处理事件绑定(这不是xbrowser安全 - 此时我犹豫建议jQuery),并且整个(el =[el]).pop()对你的伏都教来说,虽然我很高兴如果有人能够准确地解释它的成就,则予以纠正。

答案 2 :(得分: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的封闭范围相关的事实是创建一个机箱(两个,实际上 - 每个函数一个)并且可以导致浏览器泄漏。您的代码不会执行此类操作,因此不会创建任何机箱,因此不应导致(行为良好的)浏览器泄漏。

我认为只是其中一个测试版软件。 : - )