Last Updated: September 09, 2019
·
8.729K
· damln

jQuery DOM cache object

The first problem with jQuery is uncached queries.
Instead of doing something like:

$('h1').addClass('inactive');
$('h1').text('hello');
$('h1').animate({height: "100px"});

You have to do that:

var $h1 = $('h1');

$h1.addClass('inactive');
$h1.text('hello');
$h1.animate({height: "100px"});

Because the h1 is just fetched once in the DOM. This is faster.
Sometimes you will reuse this same h1 in another function. So you have to re-declare the $h1 variable, and it's not optimised.

Instead, you can do a global approach for caching DOM object from jQuery: Create a global object with the selector as key and DOM object as value. This is an implementation:

DOMCACHESTORE = {};
DOMCACHE = {
    get: function(selector, force) {
        if (DOMCACHESTORE[selector] !== undefined && force === undefined) {
            return DOMCACHESTORE[selector];
        }

        DOMCACHESTORE[selector] = $(selector);
        return DOMCACHESTORE[selector];
    }
};

How to use it?

DOMCACHE.get('h2').addClass('super');
// Later:
DOMCACHE.get('h2').removeClass('super');

This DOMCACHE.get('h2') will be the same, and it will just be fetched once.
If you have new h2 on the page, added by JavaScript, you can force the re-fetch:

DOMCACHE.get('h2', true).addClass('super');
// Now, we have all h2:
DOMCACHE.get('h2').addClass('all');

It's a very simple trick for better performance on your jQuery code.
Any suggestions or bugs? Let me know.

14 Responses
Add your response

I think two global objects is not the best javascript practice

over 1 year ago ·

You can of course encapsulate everything in a plugin or better implementation. That's why I wrote "This is an implementation".

over 1 year ago ·

Nice idea! I also wanted to combat this same issue and wrote my own protip on the subject: https://coderwall.com/p/qrbasw

over 1 year ago ·

Any reason you checked force === undefined? In this case won't false and true both force the refresh?

over 1 year ago ·

If you don't specify something (normal case) it won't force refresh. If you set something (true or other) it will force. You can check force === true if you want to be more specific.

over 1 year ago ·

You can also just chain your jQuery calls:

$('h1').addClass('inactive')
.text('hello')
.animate({height: "100px"})
over 1 year ago ·

How about something like:

$C = (function($){
    var DOMCACHESTORE = {};

    return function(selector, force) {
            if (DOMCACHESTORE[selector] !== undefined && !force) {
                return DOMCACHESTORE[selector];
            }

            DOMCACHESTORE[selector] = $(selector);
            return DOMCACHESTORE[selector];
        }
})($);

Then you can replace all your "$('h1')" with "$C('h1')", which is a lot less to type than "DOMCACHE.get('h2')".

over 1 year ago ·

I think this reads better

$C = (function($) {
  var DOMCACHESTORE = {};

  return function(selector, force) {
    if (DOMCACHESTORE[selector] === undefined || force)
      DOMCACHESTORE[selector] = $(selector);
    return DOMCACHESTORE[selector];
  }
})($);
over 1 year ago ·

@pgib : You can but sometimes you use the same selector in multiple functions. Not necessarily chaining.

@leemour : Nice one!

over 1 year ago ·

I added this to my CodePen, really usefull stuff, http://codepen.io/deiga/details/gdoKh

over 1 year ago ·

I made a JSPerf about this topic: http://jsperf.com/jquery-cached-domcache

over 1 year ago ·

I dunno, I stick to obj-pattern =\ just feels cleaner and easier to interpret down the road. pastie.org/8422291

@damln did I miss something, or is this in a different context?

over 1 year ago ·
over 1 year ago ·

You may as well just declare a global object rather than a generic cache -- you should get the benefit of Intellisense from many IDE's, which you won't from magic strings.

Also, $ME = { h1: $('h1'), somethingelse: $('whatever') } and $ME.yetanother = $('etc') is much less complicated.

over 1 year ago ·

Have a fresh tip? Share with Coderwall community!

Post
Post a tip
Did you know?

JavaScript on a page runs with the privileges of that origin. One altered library, tag manager, or snippet can read inputs, change what people see, and call your APIs as the user.

Security insights from Cside