views:

1855

answers:

4

Javascript client side application.

Trying to eliminate memory leaks leads to ugly (to say the least) code.

I am trying to clean up in window.unload instead on messing up all the code trying to avoid them.

We use mostly element.onevent=function(){..}; pattern, that results in closure (mostly wanted) and memory leak.

We do not use javascript frameworks.

Are there any ideas on how to clean up properly on exit?

Has anyone do the same or are you trying to avoid them?

A: 

I'm not sure what you mean with cleanup as JavaScript has an automatic memory management. But anyway, as I understand, after the window is unloaded, all the memory associated with JS is released as well. After all - there is no more JS executing from a page after it has unloaded, right?

Vilx-
pkario
A: 

From most of my investigations into this, there is no good way of doing this.. each individual browser has it's own implementation of garbage collection.

Firefox is not so bad, but IE6 for instance is terrible.. try and create anything over 60 objects and IE6 will become very sluggish.

Just one of those things, I've come to accept.

adam
+1  A: 

A solution for avoiding memory leaks with events is delegation. In a nutshell, you attach your event handler to a parent object instead of the children. Because of propagation, a click on a child will also register as a click on the parent, triggering your handler. By checking the target attribute of the event, you can then decide what to do with it.

Since the handler is attached to the parent, you can add or remove children without worrying about leaks.

A more thorough explanation can be found here: http://www.robertnyman.com/2008/05/04/event-delegation-with-javascript/

A demo here: http://www.robertnyman.com/test/event-delegation/event-delegation.html

+2  A: 

The best solution is for you to roll out your own method that manages event handling. Therefore, when attaching an event handler, your method can keep track of all the added events. On unload, it can unregister all the handlers.

I know you said you don't use libraries, but you can use their code as inspiration. Ext-js does that when you use Ext.EventMgr.addListener.

Here's a simple EvtMgr obj that you can use to get started. It's very simplistic, I can't write it all for you here. Feel free to ask questions about things that you'd like and don't know how to do. Also note that I wouldn't use the element.onclick method since you can only add a single handler. I'm doing it that way because you said that's how you do it.

var EvtMgr = (function(){
  var listenerMap = {};

  // Public interface
  return {
    addListener: function (evtName, node, handler) {
      node["on" + evtName] = handler;
      var eventList = listenerMap[evtName];
      if (!eventList) {
        eventList = listenerMap[evtName] = [];
      }
      eventList.push(node);
    },

    removeAllListeners: function() {
      for (var evtName in listenerMap) {
        var nodeList = listenerMap[evtName];
        for (var i=0, node; node = nodeList[i]; i++) {
          node["on" + evtName] = null;
        }
      }
    }
  }
})();

Also, beware that handlers with closures is not the only way to create leaks. See my comment on this question http://stackoverflow.com/questions/1077840/javascript-memory-leaks-after-unloading-a-web-page/1886359#1886359

Also, I don't understand why some people are afraid of libraries. jquery is tiny, ext core is too. They can be dangerous if you use them without understanding js. But if your js skills are solid, you save a lot of work by reusing their code. I get under the hood of ext-js every single day when I need to understand how somethings is done. This was how I gave you these few lines of code.

Another think to think about when managing memory leaks is to make sure you remove handlers when removing elements from the DOM (node.innerHTML or any other way). If you do that, you should remove handlers from the nodes you've removed from the DOM. There's some work to get that working but it should be part of your strategy.

Juan Mendes