title: Why does this leak in Internet Explorer 8?
body: <p>Why does the following code leak?</p>
  
  <pre><code>for (var i = 0; i &lt; 100; i++) {
      var item = {};
      item.elem = document.createElement('div');
      document.body.appendChild(item.elem);
      item.addEvent = function(name,listener) {
          var self = this;
          var wrappedListener = function() {
              return listener.apply(self,arguments);
          }
          //Uh-oh creating a circular reference here!
          //The wrappedListener has a closure on self and therefore on item.elem.
          addEvent(this.elem,name,wrappedListener);
          return wrappedListener;
      }
      var wrap = item.addEvent('eventName',listen);
  
      //Now remove the eventHandler - this should free up the circular reference.
      removeEvent(item.elem, 'eventName', wrap);
      if (item.elem.parentNode) {
          item.elem.parentNode.removeChild(item.elem);
      }
      //item.elem = null; //With this also un-commented, the leak disappears.
      //The fact that I have to null item.elem tells me that something is holding
      //a reference to item, and therefore elem. Setting elem to null fixes the
      //problem, but since I am removing the event handler, I don't think this
      //should be required.
  }
  </code></pre>
  
  <p>Note: <code>addEvent</code> and <code>removeEvent</code> are just to abstract <code>attachEvent</code>/<code>addEventListener</code> differences between Internet Explorer and other browsers.</p>
  
  <p>I created a <a href="http://jsfiddle.net/" rel="nofollow">jsFiddle</a> project which demonstrates the problem. Just fire up Internet Explorer 8 and watch it go in Task Manager or Process Explorer. Also, you will see the definition of <code>addEvent</code> and <code>removeEvent</code> there.</p>
  
  <p><a href="http://jsfiddle.net/rJ8x5/34/" rel="nofollow">http://jsfiddle.net/rJ8x5/34/</a></p>
  
  <p>EDIT: Well, I came up with the following solution. It is not pretty, but it works!
  <a href="http://jsfiddle.net/rJ8x5/43/" rel="nofollow">http://jsfiddle.net/rJ8x5/43/</a></p>
  
  <pre><code>var item = {};
  item.elem = document.createElement('div');
  document.body.appendChild(item.elem);
  item.addEvent = function(name,listener) {
      var wrappedListener = function() {
          //Access the scope through the callee properties.
          return listener.apply( arguments.callee.scope, arguments);
      }
      addEvent(this.elem,name,wrappedListener);
      //Save the scope not as a closure, but as a property on the handler.
      wrappedListener.scope = this
      return wrappedListener;
  }
  var wrap = item.addEvent('eventName',listen);
  removeEvent(item.elem, 'eventName', wrap);
  //Force the circular reference to GO AWAY.
  wrap.scope = null
  if (item.elem.parentNode) {
      item.elem.parentNode.removeChild(item.elem);
  }
  //item.elem = null; //No longer needed.
  </code></pre>