It is easy to confuse looping with JavaScript each vs in if you don't understand primitives vs objects, loop types, and higher-order array methods.
This tutorial clarifies JavaScript foreach vs forin using practical examples. It explains the necessary concepts before highlighting the similarities and differences between the forEach()
method
array.forEach( element => {
// do something with each element
})
and the for-in loop.
for (let element in object) {
// do something with each element
}
Let's get started.
Primitives vs objects
The first step to understanding JavaScript each vs in is knowing the origin of objects.
There are seven data types in JavaScript: string, number, boolean, symbol, null, undefined, and object.
The data types are further classified into primitives and objects. You cannot subdivide primitives like a number, a string, and a boolean. On the other hand, you can subdivide an object into multiple primitives.
An object is a key-value paired data. The main types of objects are functions, literals, and arrays.
// function
const saidSomething = (person, word, time) => `${person} said ${word} at ${time}.`
// object literal
const literal = { name: "Bob", meanGrade: 79.47, codes: true }
// array
const array = ["Bob", 79.47, true]
A function is a block of code that does something when called, whereas an array is a special object that holds indexed elements. You can manipulate each element of an object using a loop. But what is a loop?
Loops
A loop is a block of code that repeats an instruction as long as a condition is true. There are three primary types of loops: while, do-while, and for loops.
while
A while loop repeats a code block with an externally defined initializer, increasing or decreasing it per condition.
const array = ["Bob", 79.47, true]
let count = 0
while(count < array.length) {
console.log(array[count])
count++
}
count
is the initializer; count < array.length
, condition; and count++
, increment.
do-while
Unlike the while loop, a do-while loop runs through the code block at least once, whether the condition is false.
const array = []
let count = 1
do {
console.log("In the loop")
count++
} while (count < array.length)
We don't expect the condition to enter the loop body because the condition (count < array.length
) is false. But it does because we are using a do-while loop.
for
Unlike the while and the do-while loops, the for loop combines the initializer, condition, and the in/decrement in a statement.
const array = ["Bob", 79.47, true]
for(let count = 0; count < array.length; count++) {
console.log(array[count])
}
You can notice that the above loop types favor arrays. What if we want to print a literal? Or manipulate the array elements while returning or not returning output in various ways?
That is why other forms of the for-loop were added to JavaScript. However, this time around, you mainly use loops depending on whether you are handling an iterable or an enumerable.
So, let's discuss iterables and enumerables before diving into JavaScript each vs in.
Iterables vs enumerables
An iterable (array) object is accessible via its values. We mainly use for-of loop to handle an iterable.
const array = ["Bob", 79.47, true]
for (let value of array)
console.log(value)
An enumerable (array or object) is accessible via its keys. We mainly use the for-in loop to handle an enumerable.
console.log("...Object...")
const literal = { name: "Bob", meanGrade: 79.47, codes: true }
for (let key in literal)
console.log(literal[key])
console.log("\n...Array...")
const array = ["Lorem", 89.67, false]
for (let key in array)
console.log(array[key])
As you can see from the above explanations of for-of and for-in loops, arrays are the most catered-for data types. Not only that.
Working with JavaScript arrays is further simplified with higher-order methods.
Higher-order array methods
A regular function takes non-function arguments and manipulates them according to your need.
const saidSomething = (person, word) => {
const time = `${new Date().getHours()}${new Date().getMinutes()} hours`
return `${person} said ${word} at ${time}.`
}
const speech1 = saidSomething("Lorem", "Hello")
console.log(speech1)
If a function receives another as an argument, the calling function is higher-order.
There are many built-in higher-order functions to ease working with arrays. Some of them are map()
, reduce()
, filter()
and forEach()
. Such functions are called higher-order array methods.
const array = ["Bob", 79.47, true]
array.forEach( (element) => {
console.log(element)
})
The forEach()
method accepts a callback function that manipulates each element. For example, we run a callback function that prints every array element.
(element) => {
console.log(element)
}
The above is an anonymous function that could as well be written as a regular function.
const callbackFunction = (input) => {
console.log(input)
}
Now that you understand how the forEach function and for in loop work, let's mention the similarities and differences.
JavaScript forEach vs for/in
Similarities
The two main similarities between JavaScript forEach and for-in are both have for in their names: forEach and for in. Also, they can manipulate an array's element.
const array = ["Bob", 79.47, true]
// for Each
array.forEach(element => console.log(element))
// for in
for (let index in array) console.log(array[index])
Differences
The primary difference between the forEach()
method and for-in is that forEach()
is a higher-order function, whereas for-in is a loop primarily meant to manipulate enumerables.
// function
array.forEach(<callback function>)
// loop
for (variable in enumerable)
Besides, a for-in loop can handle other objects apart from arrays, whereas forEach()
is an array method.
Here are examples to practice using JavaScript each vs in.
Practical example
Let's get the user avatar URL from the reqres website, then save and print it with the forEach()
 method and for in loop, respectively.
Launch the terminal and create the project directory with the script file before opening the project with a code editor.
mkdir each_vs_in && cd each_vs_in
touch main.js
code .
I create the project and open it with Visual Studio Code.
Create a text file
Import the fs module and create the text file to store the user avatars.
const fs = require('fs')
fs.writeFileSync('users.txt', '...........for each............\n\n')
Fetch user data
Using the fetch API, get and return the user data.
const fetchUsers = async (url) => {
const res = await fetch(url)
const users = await res.json()
return users.data
}
Save and print the user data
Now let's run the fetchUsers
function with the target URL, loop through the users, saving the avatars with the forEach()
method and printing the data with a for-in loop, respectively.
fetchUsers("https://reqres.in/api/users").then(users => {
// save avatars with forEach() method
users.forEach(user => {
fs.appendFile('users.txt', `${user.avatar}\n`, e => e ? console.log(e): '')
})
// print the avatars
console.log("\n...........for in............\n");
for (let index in users) console.log(users[index].avatar)
}).catch(e => console.log(e))
Lastly, run the script file.
node main.js
Output
A new text file with six image URLs gets created
...........for each............
https://reqres.in/img/faces/1-image.jpg
https://reqres.in/img/faces/4-image.jpg
https://reqres.in/img/faces/2-image.jpg
https://reqres.in/img/faces/6-image.jpg
https://reqres.in/img/faces/3-image.jpg
https://reqres.in/img/faces/5-image.jpg
The console output prints similar data.
...........for in............
https://reqres.in/img/faces/1-image.jpg
https://reqres.in/img/faces/2-image.jpg
https://reqres.in/img/faces/3-image.jpg
https://reqres.in/img/faces/4-image.jpg
https://reqres.in/img/faces/5-image.jpg
https://reqres.in/img/faces/6-image.jpg
Conclusion
Distinguishing JavaScript each vs in is straightforward after understanding higher-order array methods and enumerables. You can then comfortably apply the methods and loops, as illustrated in this tutorial.