Memoization with DOM selectors in JavaScript
function getEls(sel) {
if (!getEls.cache) getEls.cache = {};
if (getEls.cache[sel]) {
console.log('from cache');
return getEls.cache[sel];
}
var r = document.querySelectorAll(sel || '☺'),
length = r.length;
return getEls.cache[sel] = (length == 1) ? r[0] : r;
}
var imgs = getEls('img');
var moreImgs = getEls('img');
var ps = getEls('p');
var morePs = getEls('p');
Written by Ben Howdle
Related protips
3 Responses
I was thinking about this too but then there is a problem if user uses:
- "#header .menu-item"
- "#header .menu-item.active"
- ".menu-item"
- ".menu-item.active"
or just typo:
1. "#header .menu-item"
2. "#header .menu-item"
But for smart people this is really useful ;)
over 1 year ago
·
Nice. There's a couple of things I'd tweak though.
- The function is called getEls, but you sometimes return multiple elements, and sometimes only one. It should be consistent, so that the user of the method doesn't have to check if what they got back was a NodeList or some kind of Element.
- I have no proof of this, but I suspect passing
sel || ☺
is inefficient. It'd be better to return early if no selector is passed. You could even return an empty NodeList usingdocument.createDocumentFragment().childNodes
- I'd recommend taking a boolean argument that, if true, forces it to bypass the cache and save that selector again.
over 1 year ago
·
What if elements are added dynamically to the page, after the initial cache has been created?
For example,
var imgs = getEls('img');
// some AJAX stuff injects more images to DOM
imgs = getEls('img') // won't this return outdated result from cache?
over 1 year ago
·
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Dom
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#