views:

89

answers:

1

I am working on refactoring a JavaScript namespace for a site. The namespace leverages jQuery for selectors and events. Here is an example.

MyNamespace = {
    eventElements : {
        headerSectionA : $("h1.section-a");
        headerSectionB : $("h1.section-b");
    }
    sectionA : function() {
        // do stuff for section A here, such as
        MyNamespace.eventElements.headerSectionA.click(function(){
            // behavior A
        });
    }
    sectionB : function() { 
        // do stuff for section B here, such as
        MyNamespace.eventElements.headerSectionB.click(function(){
            // behavior B
        });
    }
}

This is a distilled code sample. Imagine many eventElements, and many site sections that make use of subsets of those eventElements.

My question is whether jQuery traverses the DOM for all eventElements every time this script loads, or only when a function is called that uses that eventElement.

I want to avoid performance loss, but I am not sure if jQuery traverses the DOM when an eventElement property is declared, or only when an event is attached to the eventElement.

If there is a performance loss using the approach above, then I will branch within the namespace to only declare eventElements within the context of the section that makes use of those eventElements.

+3  A: 

JavaScript is executed as expressions are encountered. So yes, if this is in your script file:

MyNamespace = {
    eventElements : {
        headerSectionA : $("h1.section-a"),
        headerSectionB : $("h1.section-b")
    }
    // ...
}

Then $ is called and the DOM is traversed at the time the script is executed. This is bad on a couple levels:

  • the placement of the script is reliant on the DOM being ready to traverse (fyi the whole reason $(document).ready exists is to get around this problem)
  • the DOM is traversed before those elements need to be referenced

I'd adjust it to only do as much work as needed:

MyNamespace = {
    eventElements : {
        headerSectionA : "h1.section-a", // THESE BECOME STRINGS
        headerSectionB : "h1.section-b"
    }
    ,// ...
    sectionA : function() {
        // Call $ as late as possible
        $(MyNamespace.eventElements.headerSectionA).click(function(){
            // ...
        });
    }
}

Now if for whatever reason MyNamespace.eventElements.headerSectionA must be a jQuery object before sectionA is called, then you should at least wait to initialize them until the DOM is ready, in order to reduce the brittleness of the script itself:

// namespace defined as before
// wait until DOM is ready
$(document).ready(function() {
    for(var selector in MyNamespace.eventElements) {
        MyNamespace.eventElements[selector] = $(MyNamespace.eventElements[selector])
    }
})
Roatin Marth