Thousands of developers interact with this API on a daily basis yet most forget it is just… an API! Of course, I’m talking about the notorious “Document Object Model” (a.k.a the DOM). With the rise of “Rich Internet Applications” interaction with the DOM has sky-rocketed and as a result it’s being heavily abused!

Have you ever needed to do this? –

// E.g. 1
element.addEventListener('click', function(e){
    this.rel += ' clicked' + '(' + e.clientX + ' ,' + e.clientY + ')';
});
 
// E.g. 2
jQuery('a').mouseover(function(){
    var color = jQuery(this).css('color');
    jQuery(this).data('beforeColor', color);
    changeColor(this);
});

If you have then (in my humble opinion) you’re abusing the DOM!

The first example is obviously bad practice; using HTML attributes to track changes unrelated to the HTML content is a crime of sorts and should never be done! The second example probably doesn’t seem as bad to most developers. jQuery’s “data” method allows you to store expando-like data about an element without obtrusively defining it as a direct property. This technique of storing element data is far better than using the HTML rel attribute. Or is it?

I was an advocate of this particular technique but I’ve come to realise that it is, in most situations, no better than using any random HTML attribute. If we put the unobtrusive-vs-obtrusive argument aside, both techniques are effectively the same. Plus, jQuery’s “data” technique is not really unobtrusive – jQuery still uses an expando property to tie the element to a particular property in a JavaScript object; I’m not saying there’s anything wrong with this, I’m just pointing out the common misconception that using jQuery’s data method is somehow cleaner than using a random or made-up HTML attribute (/DOM property).

The main reason I am now so sceptical about its usage is because, over time, I’ve seen a lot of cases that don’t really require it at all and could quite easily be achieved with a well-thought-out use of JavaScript closures. Obviously it’s not all bad; there are a few valid uses – for example, jQuery currently uses its own “data” method to tie events to elements/objects; a central part of the its event dispatch system.

Magical closures

The nature of JavaScript closures allows us to use regular variables to store progress or states and then access those variables from within nested functions. I’ve put together a short example; this is an outline of a drag-and-drop script:

// Library neutral/agnostic
 
draggableElements.forEach(function(elem){
 
    var down = false,
        y = 0,
        x = 0;
 
    elem.bind('mousedown', function(e){
        down = true;
        x = e.pageX - getOffset(elem).left;
        y = e.pageY - getOffset(elem).top;
    });
 
    document.bind('mousemove', function(e){
        if (down) {
            elem.applyCSS({
                left: e.pageX - x,
                top: e.pageY - y
            });
        }
    });
 
    document.bind('mouseup', function(e){
        down = false;
    });
 
});

Every “draggable” element is given its very own closure (through forEach) within which we can define numerous variables accessible in each of the nested “handler” functions (‘mousemove’, ‘mousedown’, etc.). No expando properties are required, nada!

I haven’t got much more to say about this; the above code pretty much sums up my point!

I’m interested in valid uses of jQuery’s data() method (other than those used in the core); someone please enlighten me!

Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!