Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At what level should I cache results of jQuery DOM queries?

There are quite a few questions that ask about caching jQuery objects but I can't find one that asks where exactly jQuery objects can and should be cached. I have a web page that has a single JavaScript file with a bunch of functions as shown below.

$(document).ready(function () {

    // do some setup
});

/* function queries the DOM with the same selector multiple times without caching */
function myFunctionOne() {

    $('#name_input').css("border","1px solid #ccc");
    $('#name_input').val(someValue);        
}

/* function uses cached object from a single query */
function myFunctionTwo() {

    var nameInput = $('#name_input')
    nameInput.css("border","1px solid #ccc");
    nameInput.val(someValue);
    // do some other stuff with cached selector        
}

In myFunctionOne I inefficiently query the DOM twice whereas in myFunctionTwo I query the DOM once, cache the result in a local variable, then work with that variable. I understand that the approach in myFunctionTwo is more efficient but I am unsure as to where I should actually be caching those objects. At the minute I am caching the object at the method level but I am wondering if I can actually cache it at a higher level and then use it across multiple functions. This way I would only query the DOM once and then reuse the result in all functions in this file. An example of what I am suggesting is shown below.

$(document).ready(function () {

    // do some setup
    var nameInput = $('#name_input')
});

/* function uses cached query result from .ready function above */
function myFunctionOne() {

    nameInput .css("border","1px solid #ccc");
    nameInput .val(someValue);        
}

/* function uses cached query result from .ready function above */
function myFunctionTwo() {

    nameInput.val(someValue);
    // do some other stuff with cached selector        
}

Is this approach sensible or is there a better way of doing it? Perhaps using the .ready function is a bad place to do this kind of setup as it will slow down page load? Is there an alternative way to cache jQuery objects at an object level or should they only be cached at a function level?

like image 866
Brian Avatar asked Feb 19 '13 21:02

Brian


2 Answers

As always in these kinds of questions, don't optimize prematurely. In this case, it means don't use any caching until you notice performance problems. If your target customers use low-spec computers or mobile devices, this means you would want to test on low-spec hardware yourself so you can identify such issues. I would strongly recommend you go for clarity before trying to improve speed by adding caching.

Some further points:

  • If you are using a selector that uses an ID, it should be fast as it will use getElementById behind the scenes, so that shouldn't need caching.
  • Use method chaining instead of caching, which will only use the selector once
  • If you do implement caching, do it locally first. Caching between methods will cost more in code complexity than local caching.
  • Using .ready is fine. It runs after the DOM has been loaded, and is the exactly right place to do setup tasks.
like image 157
Peter Avatar answered Sep 30 '22 19:09

Peter


One approach could be to store the selector in the $.cache:

$(function(){

      var $nameInput = $('#name_input');

      $('body').data({ nameInput: $nameInput });

});

And then access it using:

function myFunctionOne() {

    var $nameInput = $('body').data('nameInput');
}
like image 26
Johan Avatar answered Sep 30 '22 18:09

Johan