Javascript event handlers always increase browser

2019-05-24 21:39发布

Edit: On further examination Firefox does not seem to be doing this, but Chrome definitely does. I guess its just a bug with a new browser - for every event an I/O Read also occurs in Chrome but not in FF.

When I load the following page in a browser (I've tested in Chrome and Firefox 3 under Vista) and move the mouse around the memory always increases and does not ever seems to recede.

Is this:

  1. expected behaviour from a browser
  2. a memory leak in the browser or
  3. a memory leak in the presented code?

.

<!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>

The (el = [el].pop()) and the try/finally ideas are both from here, though they do not either seem to help - understandably since they are only meant to be ie6 fixes.

I have also experimented with using the addEventListener and the onmouseover methods of adding the events. The only way I have found to prevent memory from increasing is to comment out both lines of code.

3条回答
smile是对你的礼貌
2楼-- · 2019-05-24 21:55

Well this is not how I'd handle this at all, and I can't replicate the behaviour so all I can tell you is the problem you're having memory wise is likely because of whatever is in the fn function, and unless it's a closure you should be defining fn outside of the createEl function and merely referencing it within, so only a single instance of that exists in memory.

You need to handle the event binding better though (this is not xbrowser safe - at this point I hesitate to suggest jQuery), and that whole (el =[el]).pop() reeks of voodoo cruft to me, though I'm happy to be corrected if someone can explain exactly what it achieves.

查看更多
\"骚年 ilove
3楼-- · 2019-05-24 21:59

fn is a closure even with no code in it. E.g. try debug with Firebug and set the breakpoint inside that function. All variables defined in closure (fn code + variables that hang around = closure) are theoretically accessible(though I don't know how to access them on practice).

查看更多
Melony?
4楼-- · 2019-05-24 22:01

Memory leaks related to event handlers are, generally speaking, related to enclosures. In other words, attaching a function to an event handler which points back to its element can prevent browsers from garbage-collecting either. (Thankfully, most newer browsers have "learned the trick" and no longer leak memory in this scenario, but there are a lot of older browsers floating around out there!)

Such an enclosure could look like this:

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);

The fact that fnOver and fnOut reach out to their enclosing scope to reference el is what creates an enclosure (two, actually — one for each function) and can cause browsers to leak. Your code doesn't do anything like this, so creates no enclosures, so shouldn't cause a (well-behaved) browser to leak.

Just one of the bummer of beta software, I guess. :-)

查看更多
登录 后发表回答