For f@%#’s sake, should I use ‘for…of’ or ‘for…in’?
A guide to help you Google for loops less
There are certain things that always come up regularly in web development that I just can’t seem to cement into memory — splice()
vs. slice()
, css transition syntax, arguments and proper return values in reduce()
vs. map()
vs. filter()
vs. sort()
, to name just a few…
Those may crowd my Google history, but none come close to the basic for
loop and its few, relatively simple variations.
I can’t be the only one, so let’s lay em’ all out, one-by-one, in the hopes of not having to wonder which is which every friggin’ time.
At the end of this post, I’ll provide a concise, bullet-point list of each variation and in what types of situations they make the most sense.
First things first — the basic for
loop
This is the for
loop variation we all know and love. It’s a common default option for any sort of iteration over an array, with plenty of flexibility in terms of where to start the loop, where to end, and how to move on from one iteration to the next.
This type of for
loop uses the index
position of the array to keep track of where we are in the iteration. So, we use the index
to access the actual data at that position in the array.
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];for(let index=0; index < players.length; index++){
console.log(`Player at index ${index} is ${players[index]}`)
}//====Console Output====//
Player at index 0 is Alex
Player at index 1 is Becky
Player at index 2 is Charlie
Player at index 3 is Dylan
Awesome — easy to remember how and when to use this one.
If…
- in doubt about what type of for loop to use on an array
- you want to iterate over only a portion of the array, or skip over indexes
- you want to iterate backwards, i.e. start at the end of the array and decrement the index as you go through the loop
- you don’t learn anything from the rest of this blog post
forEach
As the name suggests, this array method does not provide the flexibility of the basic for
loop — ya gotta handle each and every item in the array via a callback function passed to the method.
The callback
function takes three arguments.
currentValue
— current element in the arrayindex
— the index of the current element in the array, just like the index in the basicfor
looparray
— the array that the forEach statement is being applied to / is a method of
With forEach()
, we have two ways of outputting the players
as we did with the basic for
loop example.
One is a contrived, ugly way of outputting all of the players using forEach()
, which is virtually identical to how we used the for
loop, only here forEach()
assumes the starting index
is zero and that we’ll iterate through all of players.length
.
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];players.forEach(function(player, index, array){
console.log(`Player at index ${index} is ${array[index]}`)
})//====Console Output====//
Player at index 0 is Alex
Player at index 1 is Becky
Player at index 2 is Charlie
Player at index 3 is Dylan
Doing it this way, though, doesn’t take advantage of the brevity and efficiency offered by the forEach
method. It’s much cleaner and easier to use it like in the example below assuming we have no need for the index
, just the element
as is often the case.
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];players.forEach(player => {
console.log(`Player's name is ${player}`)
})//====Console Output====//
Player's name is Alex
Player's name is Becky
Player's name is Charlie
Player's name is Dylan
Oh, another super useful version of the forEach()
method exists on NodeLists, which are kind of like arrays of DOM elements returned by common DOM methods like querySelectorAll()
.
So, you probably want to use a forEach()
array method when…
- you want to iterate over every element in an array, and have no need to break the loop prematurely
- you have no need for the
index
of the array element being processed map()
,reduce()
,filter()
or some other built-in array method doesn’t suit your needs- iterating over NodeLists and working with the DOM in general
For…in
Who else has tried to use this on an array, only to be confused by what pops out? Anyone? Bueller?
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];for(let player in players){
console.log(`Player is ${player}`)
}//====Console Output====//
Player is 0
Player is 1
Player is 2
Player is 3
WHAT?! I WANTED THE PLAYER NAME, NOT THE INDEX!!
It works on arrays, but only provides the index of the current item, similar to the basic for
loop. And while this method of iterating over an array is valid, it’s not particularly unique or useful.
From the MDN docs…
Because the order of iteration is implementation-dependent, iterating over an array may not visit elements in a consistent order. Therefore it is better to use a
for
loop with a numeric index (orArray.prototype.forEach()
or thefor...of
loop) when iterating over arrays where the order of access is important.
The for…in
loop is meant to be used on an object, iterating over the keys of that object.
Let’s try the same for…in
loop we just used on the players
array, but instead make a team
object with our players.
const team = {
seeker: 'Alex',
chaser: 'Becky',
beater: 'Charlie',
keeper: 'Dylan'
}for(let player in team){
console.log(`${team[player]} is a ${player}`)
}//====Console Output====//
Alex is a seeker
Becky is a chaser
Charlie is a beater
Dylan is a keeper
So, when do you want to use the for…in
loop?
When…
- you want to iterate over an object, particularly the keys of that object
- iterating over an array, where the basic
for
loop is less optimal than usingfor…in
loop to get the current index of the array items
For…of
This gift from ES6 is insanely flexible and applicable, allowing you to iterate over damn near everything, with a unique operation/output for each type of iterable object, e.g. Array
, String
, function arguments
, Nodelist
, and less common or newer object types like Map
, Set
, and Symbol
.
How is it different from the for…in loop? From the MDN docs…
Both
for...in
andfor...of
statements iterate over something. The main difference between them is in what they iterate over.The
for...in
statement iterates over the enumerable properties of an object, in original insertion order.The
for...of
statement iterates over data that iterable object defines to be iterated over.
Using our previous players
array, we can see how for…of
could replace the need for the forEach
or basic for
loops.
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];for(let player of players){
console.log(player)
}//====Console Output====//
Alex
Becky
Charlie
Dylan
You may want to use the for…of
loop when…
- iterating over pretty much anything iterable — so not
Objects
! - trying to incorporate new, more modern JavaScript in your code
A quick reference of everything in this post
Use a basic for
loop when…
- in doubt about what type of for loop to use on an array
- you want to iterate over only a portion of the array, or skip over indexes
- you want to iterate backwards, i.e. start at the end of the array and decrement the index as you go through the loop
Use the forEach method when…
- you want to iterate over every element in an array, and have no need to break the loop prematurely
- you have no need for the
index
of the array element being processed (though still accessible using callback function parameters) map()
,reduce()
,filter()
or some other built-in array method doesn’t suit your needs- iterating over NodeLists and working with the DOM in general
Use a for…in loop when…
- you want to iterate over an object, particularly the keys of that object
- iterating over an array, where the basic
for
loop is less optimal than usingfor…in
loop to get the current index of the array items
Use a for…of loop when…
- iterating over pretty much anything iterable — so not
Objects
! - trying to incorporate new, more modern JavaScript in your code
Examples
for
loop
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];for(let index=0; index < players.length; index++){
console.log(`Player at index ${index} is ${players[index]}`)
}//====Console Output====//
Player at index 0 is Alex
Player at index 1 is Becky
Player at index 2 is Charlie
Player at index 3 is Dylan
forEach
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];players.forEach(player => {
console.log(`Player's name is ${player}`)
})//====Console Output====//
Player's name is Alex
Player's name is Becky
Player's name is Charlie
Player's name is Dylan
for…in
const team = {
seeker: 'Alex',
chaser: 'Becky',
beater: 'Charlie',
keeper: 'Dylan'
}for(let player in team){
console.log(`${team[player]} is a ${player}`)
}//====Console Output====//
Alex is a seeker
Becky is a chaser
Charlie is a beater
Dylan is a keeper
for…of
const players = ['Alex', 'Becky', 'Charlie', 'Dylan'];for(let player of players){
console.log(player)
}//====Console Output====//
Alex
Becky
Charlie
Dylan