Iterating over an array to search for an item is a pretty common task. With JavaScript, Array.prototype.forEach is often the popular choice. In some cases however, Array.prototype.some can be a better fit for the job if there is no need to search the entire array once a condition is fulfilled.
There are at least three different ways to iterate over arrays and objects in JavaScript: for loops, array methods, listing property keys. If the iteration is being carried out to perform a search operation, it may lead to the following example:
function findEmployee(id) {
for (var i in employees)
if (employees[i].id === id)
return employees[i];
}
Without any guards and error checks, the code above is rather self-explanatory. Now, since JavaScript Array has some powerful higher-order functions, one certainly can tweak the above code to look like this:
function findEmployee(id) {
var employee;
employees.forEach(function (e) {
if (e.id === id) employee = e;
});
return employee;
}
Let us review what the specification says about Array.prototype.forEach
(Section 15.4.4.18):
callbackfn should be a function that accepts three arguments.
forEach
calls callbackfn once for each element present in the array, in ascending order.
In our example problem, supposed that the employee’s id is unique (ideally of course this would be an associative container, see also the blog post Determining Objects in a Set, but that is a different story). The search via forEach
is rather inefficient, it will continue even though there is already a hit. It is mandated by the above specification, invoking the callback once for each element present.
An improvement to the search would be to stop right away once the condition is fulfilled. Note that the condition needs not be only a single match. There are problems like searching the first 3 free spaces, locating enough suitable rooms, etc. Fortunately, there are Array methods which can do that: every
and some
. I have covered the use of every
to implement a primality test (see the previous blog post on Prime Numbers, Factorial, and Fibonacci Series with JavaScript Array) so let us take a look at its sibling.
Section 15.4.4.17 of ECMAScript 5.1 specification reveals that for Array.prototype.some:
callbackfn should be a function that accepts three arguments and returns a value that is coercible to the Boolean value
true
orfalse
.some
calls callbackfn once for each element present in the array, in ascending order, until it finds one where callbackfn returnstrue
.
This is exactly what we need! Rewriting the previous code fragment gives the following version. The iteration will not continue if there is a match.
function findEmployee(id) {
var employee;
employees.some(function (e) {
if (e.id === id) {
employee = e;
return true;
}
});
return employee;
}
Did you ever encounter a situation where some
can be used instead of forEach
? Tell us!