Seeking for faster $.(':data(key)')
- by PoltoS
I'm writing an extension to jQuery that adds data to DOM elements using
el.data('lalala', my_data);
and then uses that data to upload elements dynamically.
Each time I get new data from the server I need to update all elements having
el.data('lalala') != null;
To get all needed elements I use an extension by James Padolsey:
$(':data(lalala)').each(...);
Everything was great until I came to the situation where I need to run that code 50 times - it is very slow! It takes about 8 seconds to execute on my page with 3640 DOM elements
var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
jQuery(':data(lalala)').each(function() {
x++;
});
};
console.log(((new Date).getTime()-t)/1000);
Since I don't need RegExp as parameter of :data selector I've tried to replace this by
var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
jQuery('*').each(function() {
if ($(this).data('lalala'))
x++;
});
};
console.log(((new Date).getTime()-t)/1000);
This code is faster (5 sec), but I want get more.
Q Are there any faster way to get all elements with this data key?
In fact, I can keep an array with all elements I need, since I execute .data('key') in my module. Checking 100 elements having the desired .data('lalala') is better then checking 3640 :)
So the solution would be like
for (i in elements) {
el = elements[i];
....
But sometimes elements are removed from the page (using jQuery .remove()). Both solutions described above [$(':data(lalala)') solution and if ($(this).data('lalala'))] will skip removed items (as I need), while the solution with array will still point to removed element (in fact, the element would not be really deleted - it will only be deleted from the DOM tree - because my array will still have a reference).
I found that .remove() also removes data from the node, so my solution will change into
var toRemove = [];
for (vari in elements) {
var el = elements[i];
if ($(el).data('lalala'))
....
else
toRemove.push(i);
};
for (var ii in toRemove)
elements.splice(toRemove[ii], 1); // remove element from array
This solution is 100 times faster!
Q Will the garbage collector release memory taken by DOM elements when deleted from that array?
Remember, elements have been referenced by DOM tree, we made a new reference in our array, then removed with .remove() and then removed from the array.
Is there a better way to do this?