Here is a helper function that converts an array like object into an actual array and then loops through the iterable, supplying each value in the list to the callback function:
var each = function(iterable, callback) {
iterable = Array.prototype.concat.apply([], iterable);
for(var i = 0; i < iterable.length; i++) {
callback.apply(iterable[i], [iterable[i], i]);
}
return iterable;
};
Here I'm using the aforementioned helper function, to loop through arrays:
var found = [];
each(arguments, function(argument) {
each(argument.split(","), function(selector) {
each(handle(selector), function(element) {
if(found.indexOf(element) < 0) {
found.push(element);
}
});
});
});
The first loop goes through the arguments. The second loop splits the selectors and the third loop goes through the requested elements and adds them to the found
array (if they haven't already been added).
NOTE: the handle
function takes the selector (a string) and returns a list of elements using document.querySelectorAll
.
This script works but the problems are readability and performance.
Performance problems occur when there are many arguments that contain multiple (~5-10) comma separated selectors that are then individually handled by the handle
function.
I fixed this by using classes instead of id's.
Then comes the issue of readability, which I tried to fix by moving the second loop outside of the parent loop but this required the creation of more variables and the only difference it made was changing where the each
loop was, which made readability even worse, given that there was more code to read.
Question: How can I refactor my code to reduce the amount of nested loops?
Also, is it necessary to have the first loop? If I don't use it how will I loop through the arguments to split them to get each individual selector? I know the split
method is for the String
type and can't be called on arrays.
NOTE: I'm using vanilla JavaScript and not including any libraries, frameworks or external scripts.