Archive for February, 2014

JavaScript & DOM Event Handlers

Posted: February 25, 2014 in Javascript
Tags: , ,

During end of last year we faced some serious browser memory leak issues in one of our projects.As we dug deep into the problem we found that event handlers were not detached from the HTML elements properly and somehow these objects were not removed from the memory even when not in use.So the memory consumption was gradually increasing as new HTML elements were added to the DOM after each AJAX call. Finally, we fixed the problem and the standards i.e. do’s and don’ts were updated as usual.This project used jQuery and all the focus went towards how to avoid this in jQuery without delving deep into why this happens in jQuery.I always find this library dependent understanding a very risky proposition particularly in areas where the underlying matter is so simple to understand.

The most simple way to attach an event with a HTML element is as shown below:

evt1

The basic problem with this approach is mixing of HTML & javascript code going against the concept “unobtrusive javascript”. The other way of doing this by assigning a function to the event as shown below:

evt2

This approach solves the problem mentioned above. But both these approaches suffers from the drawback that there is no way to detach the event handler if required.The DOM Level 2 Event model provides the following functions using which it can be achieved:

  • target.addEventListener(type, listener[, useCapture])
    • type – event type
    • listener – function which will be triggered
    • useCapture – true/false indicating whether the event will be captured or not.
  • target.removeEventListener(type, listener[, useCapture])
    • type – event type
    • listener – function which will be triggered
    • useCapture – true/false indicating whether the event will be captured or not.

However in IE 5-10 these functions are named as attachEvent & detachEvent and IE 11 onwards it’s the standard set of functions as mentioned above.

Note, that to remove the handler also we need reference to the handler that we want to remove.Now lets try to develop to wrapper functions in order to add & remove events from any HTML element.

The following function attaches a handler to a HTML element and stores the reference of that handler in a cache.

image

This cache store is used to obtain the reference back when the handler is removed as shown below:

image

So in order attach & detach events we need to call them in pair. Since we need reference of the handler we just can’t use removeEventListener without having that reference.

jQuery follows quite similar coding style, it stores the event handlers in an internal variable $.cache. The reference is added to the cache when we use on/bind function and removed from the cache when we use off/unbind. So it’s always a good practice to use them in pair, otherwise a reference will remain stored in $.cache leading to memory issues.