Looping Through an Array
Visit every item of an array with a for loop, a for...of loop or forEach, and use a loop to add up or count things, such as a playlist's total play time.
Apprentice · JavaScript · Updated
After this lesson you can
- Loop through every item of an array with for, for...of and forEach
- Use a loop to add up or count an array's items
Key takeaways
- A loop lets one block of code work on every item, however long the array is.
- Use a
forloop when you need the index, such as for track numbers. Stop ati < playlist.length, never at the length itself. for...ofhands you each item in turn, with no index to manage.forEachruns a function you give it once for each item. It can't be stopped early withbreak.- To add up or count, start a variable at 0 before the loop and add to it inside the loop.
Before the trip, you want the playlist printed with track numbers, the total play time worked out, and a count of the long songs. Doing that by hand for five songs is fine; for fifty, it's an evening gone. A loop does it for you: it runs the same lines of code once for every item in the array. Showing every product on a store page, totaling a shopping cart and counting unread messages all work this way.
A for loop with an index
In Module 1 you met the for loop, which counts. Counting is exactly what you need to visit every index of an array, from 0 up to the last one:
const playlist = ['Highway Sunrise', 'Desert Radio', 'Windows Down'];
for (let i = 0; i < playlist.length; i++) {
console.log(`${i + 1}. ${playlist[i]}`);
}
1. Highway Sunrise
2. Desert Radio
3. Windows Down
Read the first line as "start i at 0; keep going while i is less than the playlist's length; add 1 to i after each round". Inside the loop, playlist[i] is the song at that index, and i + 1 turns the index into a track number, since people count from 1.
The loop stops when i reaches the length, and that's on purpose. Write i <= playlist.length (read "less than or equal to") and the loop runs one extra time, at an index where there's no song:
const playlist = ['Highway Sunrise', 'Desert Radio', 'Windows Down'];
for (let i = 0; i <= playlist.length; i++) {
console.log(playlist[i]);
}
Highway Sunrise
Desert Radio
Windows Down
undefined
That's the off-by-one error from What Is an Array, inside a loop. When a loop prints undefined at the end, look at its condition first.
for...of: each item, no index
Often you don't need the index at all: you want each song, one after another. The for...of loop (read "for of") does exactly that:
const playlist = ['Highway Sunrise', 'Desert Radio', 'Windows Down'];
for (const song of playlist) {
console.log(`Now playing: ${song}`);
}
Now playing: Highway Sunrise
Now playing: Desert Radio
Now playing: Windows Down
Read it as "for each song of the playlist". Each time around, song holds the next item. There's no i to start, check or add to, so there's no off-by-one to make. song is a const because it's a fresh variable each time around, and you don't change it inside the loop. break, from Module 1, still works: it stops the loop early.
forEach: hand over a function
Arrays also have a method that loops for you: forEach. You give it a function, and it calls that function once for each item, passing the item in. A function you hand to another piece of code, for it to call when it's ready, is called a callback function: the array "calls you back" with each item.
const playlist = ['Highway Sunrise', 'Desert Radio', 'Windows Down'];
playlist.forEach(song => console.log(song.toUpperCase()));
playlist.forEach((song, index) => {
console.log(`Track ${index + 1}: ${song}`);
});
HIGHWAY SUNRISE
DESERT RADIO
WINDOWS DOWN
Track 1: Highway Sunrise
Track 2: Desert Radio
Track 3: Windows Down
The callbacks are arrow functions, from Function Expressions and Arrow Functions: song => ... is read "song, arrow...". If the callback takes a second parameter, forEach passes the item's index there too. One difference matters: forEach always visits every item. break doesn't work inside it, so when you need to stop early, use for or for...of.
Try it. Make a file named tracks.js with an array of four songs. Print them three times: with a for loop and track numbers, with for...of, and with forEach. Run it with node tracks.js.
Adding things up
Loops really pay off when they work something out. To get the trip's total play time, keep a running total, the way you'd add up a receipt in your head: start at 0, then add each song's length as you go.
const songLengths = [214, 187, 243, 198];
let totalSeconds = 0;
for (const seconds of songLengths) {
totalSeconds += seconds;
}
const minutes = Math.floor(totalSeconds / 60);
const leftOver = totalSeconds % 60;
console.log(`${totalSeconds} seconds is ${minutes} min ${leftOver} s`);
842 seconds is 14 min 2 s
+= is read "plus equals": totalSeconds += seconds means "add seconds to totalSeconds". The total is a let, because it changes every time around, and it's declared before the loop. Declared inside, it would start again at 0 for every song. After the loop, Math.floor and % (from Module 1) turn the seconds into minutes and seconds.
Counting things
Counting works the same way, with an if deciding which items count. Here's how many songs are longer than four minutes (240 seconds):
const songLengths = [214, 187, 243, 198, 305];
let longSongs = 0;
for (const seconds of songLengths) {
if (seconds > 240) {
longSongs++;
}
}
console.log(`${longSongs} of ${songLengths.length} songs are over 4 minutes`);
2 of 5 songs are over 4 minutes
longSongs++ adds 1, as i++ does in a for loop. The same shape finds the longest song too: start with 0, and inside the loop replace it whenever a song is longer.
Try it. In tracks.js, add an array of four song lengths in seconds. Print the total play time and how many songs are shorter than 3 minutes (180 seconds).
Which loop?
| You need | Use |
|---|---|
| The index, such as track numbers, or to go backward or skip items | for (let i = 0; i < list.length; i++) |
Each item, and maybe to stop early with break |
for (const item of list) |
| A function run for every item, with no stopping early | list.forEach(item => ...) |
All three visit the same items. Pick the one that says what you mean most plainly.
Check yourself
2 questions to try on the lesson page.
So what
A loop turns "do this for one song" into "do this for every song", whether the list has three items or three thousand. Totals, counts and printed lists in every app you'll build start with one of these three loops.