Douglas Crockford, and thus, JSLint really dislike for loops. Most of the time I agree, and use [].forEach
and Object.keys(obj)
to iterate through arrays or dictionaries.
However, there are cases where the built in functions are not better than a for loop in any reasonable sense (as far as I know), and I dislike having warnings on my JSLints.
One such case is, when one has a bunch of items on a canvas. When drawing, you want to iterate through the array forwards, but when hit testing a mouse click, you need to iterate backwards. E.g.
// ...
drawItems = function () {
objects.forEach(drawItem);
},
hitTest = function (x, y) {
var i;
for (i = objects.length - 1; i >= 0; i -= 1) {
if (test(objects[i], x, y)) {
return objects[i];
}
}
}
// ...
I can think of a couple of ways to pass the test, but they are all clunky. E.g.
hitTest = function (x, y) {
var item;
objects.reverse();
objects.some(function (v) {
if (test(v)) {
item = v;
return true;
}
});
objects.reverse();
return item;
}
and
hitTest = function (x, y) {
return objects.reduceRight(
function (prev, curr) {
return prev || (
test(curr, x, y)
? curr
: prev
);
},
undefined
);
}
Which will pass JSLint happily, but, to be honest, look disgusting. I don't like the idea of "hacking" my code just to make it pass a test.
Other than choosing the "tolerate for statement" option (because that affects the linting of the rest of the code), how would I deal with this whilst avoiding wasteful operations like reversing or copying the array?