×
By the end of this chapter, you should be able to:
some
and every
to iterate through an array and return a boolean.find
and findIndex
to locate elements and indexes in an array.To figure out if ANY single value satisfies a condition in an array, we can use the some
function. This will return true
if ANY value passes a condition specified in the callback, and false
if all values fail the condition.
let arr = [1,2,3,4]; let anythingGreaterThanTwo = arr.some(function(val){ return val > 2; }); let anyStrings = arr.some(function(val){ return typeof val === "string"; }); anythingGreaterThanTwo; // true anyStrings; // false
You can read more about some
here.
To figure out if ALL values satisfy a condition in an array, we can use the every
function. This will return true
if ALL values pass a condition specified in the callback. If even one value fails the condition, every
will return false
.
let arr = [1,2,3,4]; let everythingGreaterThanTwo = arr.every(function(val){ return val > 2; }); let everythingLessThanFive = arr.every(function(val){ return val < 5; }); everythingGreaterThanTwo; // false everythingLessThanFive; // true
You can read more about every
here.
find
was added to JavaScript in ES2015 to make it easier to find an element in an array based on some condition. This iterator will return the first value in an array that satisfies a condition (an expression that returns true
in the callback).
let arr = [-3,1,8,4]; let firstValueGreaterThanTwo = arr.find(function(val){ return val > 2; }); firstValueGreaterThanTwo; // 8
You can read more about find
here.
To find the first index in an array that satisfies a condition (an expression that returns true
in the callback) - we can use the findIndex
function.
let arr = [-3,1,8,4]; let firstIndexOfElementGreaterThanTwo = arr.findIndex(function(val){ return val > 2; }); firstIndexOfElementGreaterThanTwo; // 2
You can read more about findIndex
here
By combining iterators, you can often manipulate arrays using a sequence of very simple functions, rather than one larger, more complex loop. For example, suppose you wanted to take an array of numbers, filter out the even ones, double the remaining values, and then add everything up. We can do this by chaining three iterators together:
let arr = [1,2,3,4,5] arr.filter(function(val){ return val % 2 !== 0; // only keep odd numbers }).map(function(val){ return val * 2; // double remaining values }).reduce(function(acc,next){ return acc + next; // add everything up },0) // 18
This sort of chaining helps keep your code easy to reason about, because each callback is only responsible for one thing. To make things even more readable, you could give names to the callbacks:
let arr = [1,2,3,4,5]; function isNumberOdd(val) { return val % 2 === 1; } function doubleValue(val) { return val * 2; } function sum(a,b) { return a + b; } arr.filter(isNumberOdd) .map(doubleValue) .reduce(sum,0); // 18
By keeping the code inside of our functions simple, we can reduce (no pun intended) the likelihood that we'll introduce bugs into our code, and when we come back to our code weeks or months later, it'll hopefully be easier for us to wrap our heads around.
Just because JavaScript has a lot of different iterators, this doesn't necessarily mean you should always use an iterator in place of a for
loop. One of the biggest advantages to using a for loop is that you can break out of the loop or continue to the next iteration using the keywords break
and continue
. If you try to use these keywords inside of an iterator, however, you'll get a SyntaxError
.
Now that you've seen some iterators, let's highlight some situations when you might want to use one over another. If you're used to writing for
loops you'll probably be most likely to use forEach
, but this isn't always the best iterator for the job:
let arr = [1,2,3] // using forEach let newArr = []; arr.forEach(function(val){ newArr.push(val*2); }); // In the above example, we're creating a new array // with the same length as the old array. So instead // of forEach, we can refactor to use map: let newArr = arr.map(function(val){ return val*2; });
let arr = [1,2,3] // using forEach let newArr = []; arr.forEach(function(val){ if(val >= 2){ newArr.push(val); } }) // In the above example, we're creating a smaller array. // We're also not changing any values. So instead // of forEach, we can refactor to use filter: // refactor to use filter let newArr = arr.filter(function(val){ return val >= 2; })
Before using an iterator, it's always good to ask whether forEach
is the best candidate for the job, or whether another iterator would be more appropriate. If you're trying to manipulate values in an array to return a new array of the same length, map
is probably a better choice. If you're trying to remove some elements in the array and keep others, filter
is more likely the way to go. And if you're looking to take an array and output some other value (a number, a string, an object, etc.), consider whether or not you can use reduce
to get the job done.
When you're ready, move on to Iterators Exercises