In your edited question, you've said:
I am particularly interested in comparing the solutions provided here
Is it better to use a chisel or a screwdriver to pound in a nail? The only correct answer is: Neither, use a hammer.
Comparing two solutions both using the wrong tool for the job ends up being a matter of opinion. Do you prefer simplicity? Go with the forEach
. Brevity? Go with reduce
. I would flag up either in a code review as being a suboptimal choice, and would view neither as more or less suboptimal than the other.
My original answer:
In this case, neither. Array#some
(MDN | spec) would be the appropriate choice for determining whether an array has at least one entry that matches a criterion:
var hasEven = function(collection) {
return collection.some(function(entry) {
return entry % 2 === 0;
});
};
Array#some
stops looping as soon as the callback returns a truthy value. The return value of some
is true
if the callback returned a truthy value, or false
if it didn't (all elements were tested and none matched).
Or with ES2015:
// ES2015 (aka ES6) only
let hasEven = function(collection) {
return collection.some(entry => entry % 2 === 0);
};
Or we can get really condensed (possibly at the expense of readability, but maybe not when we're all really used to arrow functions):
// ES2015 (aka ES6) only
let hasEven = collection => collection.some(entry => entry % 2 === 0);
(This section references the code in your original question.)
I should note that neither of your example implementations works, neither the forEach
nor the reduce
one. The forEach
one will always return false
, because the return true
inside the callback is just returning from the callback and doesn't have any effect at all. The reduce
one will A) fail to test the first entry in the array; B) only tell you whether the last entry in the array is even, not if any of the previous ones were; and C) Return the value of the first entry if called on an array with only one entry, rather than either true
or false
.
A correct forEach
would look like this (but will loop unnecessarily):
var hasEven = function(collection) {
var result = false;
collection.forEach(function(entry) {
result = result || entry % 2 === 0;
});
return result;
};
A correct reduce
version would look like this (but will loop unnecessarily):
var hasEven = function(collection) {
return collection.reduce(function(result, current) {
return result || current % 2 === 0;
}, false);
};
Note that in the above, I used
return entry % 2 === 0;
rather than
return (entry % 2 === 0) ? true : false;
The result of ===
is already a boolean.