Array Iterator Methods Walk-Through

Learning Objectives
Students Will Be Able To: |
---|
Identify the Purpose (Use Case) of Several Useful Array Iterator Methods |
Videos
Intro
JavaScript Arrays have lots of helpful built-in methods.
These methods enable us to write code following a modern functional programming approach verses that of imperative programming.
Imperative Programming
Imperative programming is a more step-by-step way of writing code.
for
loops, for example, are imperative:
for (let index = 0; index < array.length; index++) {
// do stuff
}
With a for
loop we're saying:
- Initialize a looping variable
- Use the looping variable to access an element in the array
- Increment the looping variable
- If the looping variable is less than the length of the array, loop again
Functional/Declarative Programming
In functional/declarative programming, we write code that describes what we want to do:
array.forEach(function(val, idx) {
// do stuff
});
How are we iterating? We, don't need to worry about that.
Method Summary
Method | Purpose | Returns | Callback Should | Callback's Args |
---|---|---|---|---|
forEach(cb) | General purpose | undefined | Do whatever needs to be done | (elem, idx) |
map(cb) | Transform source array into a new array | New array | Return what goes in the new array | (elem, idx) |
filter(cb) | Filter source array | New array | Return truthy value if current elem is to be included in new array | (elem, idx) |
find(cb) | Find a certain element | The "found" elem , otherwise undefined | Return truthy when elem is "found" | (elem, idx) |
findIndex(cb) | Find the index of a certain element | The index of the first elem "found", otherwise -1 | Return truthy when elem is "found" | (elem, idx) |
some(cb) | Check if at least one element matches a condition | true or false | Return truthy if elem is what you're checking for | (elem, idx) |
every(cb) | Check if every element matches a condition | true or false | Return truthy if elem is what you're checking for | (elem, idx) |
reduce(cb, initAcc) | Reduce the array to a single value/object | Final value of acc (accumulator) | Return the new value of acc for the next iteration | (acc, elem, idx) |
Observations
The following observations will make it easier to remember the syntax of these important methods...
-
Each of the methods invoke a callback function for each iteration.
-
Most methods have to iterate over the entire array in order to fulfil their purpose, however, the following methods will "short circuit" and stop iterating once their return value has been determined:
find
: Stops iterating when the callback returns a truthy valuefindIndex
: Stops iterating when the callback returns a truthy valuesome
: Stops iterating when the callback returns a truthy valueevery
: Stops iterating when the callback returns a falsy value
VOCAB: Note that the
filter
,find
,findIndex
,some
andevery
iterator methods rely on the truthy-ness or falsy-ness returned by the callback function. In programming, a function designed to returntrue
orfalse
is called a predicate function.
-
All of the iterator methods, except
reduce
, have identical signatures, that is, they all accept a single argument - a callback function.Additionally, the signature of that callback functions are all the same as well!
Code Examples
forEach
PURPOSE: General purpose iterator method.
const friends = ["Melissa", "Marc", "Andrew", "Nick"];
friends.forEach(function(friend) {
console.log(`I have a friend named ${friend}`);
});
// logs out "I have a friend named <friend's name>" for each friend
YOU DO
Using forEach
log out each of my friends
but with the first letter of their name lower-cased. Use the <str>.toLowerCase()
method.
"Cats".toLowerCase(); //=> cats
map

PURPOSE: Create a new array from a source array by replacing or transforming its elements.
The returned array is always the same length as the source array.
Transform an array
const nums = [1, 2, 3];
const squared = nums.map(function(num) {
return num * num;
});
// squared -> [1, 4, 9]
/*--- using an arrow function for the callback ---*/
const squared = nums.map((num) => num * num);
The new elements can be anything
Here we want to map an object of "people" objects into an array of DOM elements:
const people = [
{name: 'Fred', town: 'Bedrock'},
{name: 'Susan', town: 'Miami'},
{name: 'John', town: 'Arcadia'}
];
const els = people.map((person, idx) => {
const el = document.createElement('div');
el.innerHTML = `${person.name} <span>(${person.town})</span>`;
// The new array will contain whatever
// is returned from the callback
return el;
});
// Append the <div>s to the end of the <body>
els.forEach(el => document.body.append(el));
YOU DO
Given an array of instructors,
const instructors = ["Alex", "Stephanie", "Daniel"];
Use map
to create a new array that adds the string " is awesome" to each element in the array.
["Alex is awesome", "Stephanie is awesome", "Daniel is awesome"]
filter

PURPOSE: Select certain elements from a source array.
Obtain just the odd numbers
const nums = [100, 2, 5, 42, 99];
const odds = nums.filter((num) => num % 2);
// odds -> [5, 99]
YOU DO
Filter out all "jerks"!
const people = ["jerks", "nice people", "jerks", "nice people", "nice people"];
find

PURPOSE: Find an element within an array.
Find a certain car object
const cars = [
{color: 'red', make: 'BMW', year: 2001},
{color: 'white', make: 'Toyota', year: 2013},
{color: 'black', make: 'Ford', year: 2014},
{color: 'white', make: 'Tesla', year: 2016}
];
const firstWhiteCar = cars.find((car) => car.color === 'white');
// firstWhiteCar -> {color: 'white', make: 'Toyota', year: 2013}
const missingCar = cars.find((car) => car.color === 'blue');
// missingCar -> undefined
YOU DO
Find the first car whose year is older than 2014 and assign it to a variable named notTooOldCar
;
findIndex

PURPOSE: Like find
above, but returns the found element's index instead of the element. Note that this is usually used to find the index of an object, or one of its built-in variations (Array, Date, Regular Expression, Error) within the array. If trying to find the index of a primitive type, use indexOf instead.
Find the index of the first match
const cars = [
{color: 'red', make: 'BMW', year: 2001},
{color: 'white', make: 'Toyota', year: 2013},
{color: 'black', make: 'Ford', year: 2014},
{color: 'white', make: 'Tesla', year: 2016}
];
const idxFirstCarNewerThan2015 = cars.findIndex((car) => car.year > 2015);
// idxFirstCarNewerThan2015 -> 3
// findIndex returns -1 if callback never returns a truthy value
const missingCarIdx = cars.findIndex((car) => car.year > 2020);
// missingCarIdx -> -1
some

PURPOSE: Check if array has at least one element that meets a certain condition.
Henry would be proud...
const cars = [
{color: 'red', make: 'BMW', year: 2001},
{color: 'white', make: 'Toyota', year: 2013},
{color: 'black', make: 'Ford', year: 2014},
{color: 'white', make: 'Tesla', year: 2016}
];
const hasFord = cars.some((car) => car.make === 'Ford');
// hasFord -> true
YOU DO
Do I have an evil monkey in my room?
const myRoom = ["evil monkey", "bed", "lamp"];
const isEvilMonkeyInRoom = /* Fill code in here */
every

PURPOSE: Check if every element in the array meets a certain condition.
Are all cars newer than 2000?
const cars = [
{color: 'red', make: 'BMW', year: 2001},
{color: 'white', make: 'Toyota', year: 2013},
{color: 'black', make: 'Ford', year: 2014},
{color: 'white', make: 'Tesla', year: 2016}
];
const everyCarIsNewerThan2000 = cars.every((car) => car.year > 2000);
// everyCarIsNewerThan2000 -> true
reduce

PURPOSE: Reduce an array into a single value or thing (such as an object).
Sum up the numbers in an array
const nums = [25, 6, 100, 3];
// The callback returns the value of
// acc (accumulator) for the next iteration.
// The second argument, `0`, is the value
// of acc on the first iteration.
const sum = nums.reduce((acc, num) => acc + num, 0);
// The reduce method returns whatever the callback
// returns for the last iteration.
// sum equals 134 (the final value returned)
Count votes
The reduce
method can return any single thing, such as an object!
const votes = ['Yes', 'No', 'No', 'Yes', 'Yes'];
const tally = votes.reduce((acc, vote) => {
// Assign 1 if first time seeing a certain "type" of vote
// otherwise increase count by 1
acc[vote] = acc[vote] ? acc[vote] + 1 : 1;
return acc;
}, {}); // Note the initial value is an empty object
// tally -> {"No": 2, "Yes": 3}