I have the following code which iterates through some divs of an array to show()
them. I was wondering if there is any way to rewrite the for
loop using filter()
. Will this have a better performance over my initial code?
var selectEnabledGenerators = function(generators) {
//List of generator indexes to show
var list = generators;
var allGenerators = $(".generatorContainer");
//Hide all generators
allGenerators.hide();
//maybe use filter here?
for (var i = 0, max = list.length; i < max; i++) {
$(".generatorContainer[data-generator=" + list[i] + "]").show();
}
};
2 Answers 2
I was wondering if there is any way to rewrite the
for
loop usingfilter()
.
What if I say you can avoid for
loop completely.
Yes, you can avoid loop by letting jQuery do that for you. jQuery accepts multiple comma-separated selectors and internally iterate over each selector and perform operations.
generators
is an array of elements, this array elements can be joined with ,
as glue, to create the selector.
Let's say, we have an array var selectors = ['#someId', '.myClass', 'tag']
and we want to add a class to all these selectors. We can iterate over the array and add the class to each element individually or we can combine the array elements somehow to create a comma-separated string and pass this to jQuery
as selector.
$(selectors.join(', ')).addClass('magic');
selectors.join(', ')
will join the array elements by ,
, thus giving '#someId, .myClass, tag'
which is valid selector and can be passed to jQuery
and any method defined on jQuery
prototype can be called on it.
Same logic can be used, in your case.
As join
will add the glue between the elements of array, the prefix and suffix need to be concatenated.
The selector can be created using
'.generatorContainer[data-generator="'
+ list.join('"], .generatorContainer[data-generator="')
+ '"]'
Line #1 is the prefix
Line #2 will give firstElement"], .generatorContainer[data-generator="secondElement"], ..., .generatorContainer[data-generator="lastElement
Line #3 will add suffix to make the selector valid.
With this, the code will be
var selector = '.generatorContainer[data-generator="' + list.join('"], .generatorContainer[data-generator="') + '"]';
$(selector).doMagic(); // He He
To add to the complexity, not()
can be used to exclude elements
$('.generatorContainer').not(selector).hide(); // Hide those except in array
$(selector).show(); // Show only those in array
This is kinda pointless:
var list = generators;
The
generators
argument is already a local variable. I get you might want to call it by a different name, but in that case the parameter should be calledgeneratorIndices
or something more descriptive.The
allGenerators
variable isn't necessary. It could be, but you're not reusing it. You could just write$(".generatorContainer").hide();
.
And yes, you can use jQuery's filter. You've already found all .generatorContainer
elements once, so that's the collection you want to filter.
I'd probably just do:
var selectEnabledGenerators = function (generatorIndices) {
var containers = $(".generatorContainer").hide();
generatorIndices.forEach(i => containers.filter(`[data-generator=${i}]`).show() );
};
-
1\$\begingroup\$ I'll suggest to add the quotes in attribute-value selector to value. As the array elements value is not shown in the question, it's better to wrap the value in quotes when used in selector to avoid strange results when value contains spaces or special characters. You can use
[data-generator="${i}"]
. Also, this is ES6. If target environment does not support it, you can mention to use normal functions instead of arrow functions and string concatenation instead of template literals. \$\endgroup\$Tushar– Tushar2016年12月28日 04:17:09 +00:00Commented Dec 28, 2016 at 4:17
join
on array to create a comma-separated selector and avoidfor
loop completely. You can use'.generatorContainer[data-generator="' + list.join('"], .generatorContainer[data-generator="')
\$\endgroup\$for
orwhile
loops are the quickest way iterate over any array. To further improve performance use the DOM API to query for elements rather than jQuery. \$\endgroup\$