How to Loop Through Arrays Using JS for Loops Guide

Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.

6 min read

Looping through an array is the most common real-world use of a JavaScript for loop. An array holds a list of items, and a loop lets you visit each item one at a time to read it, change it, or use it to build something new.

There are three main ways to iterate over an array with a loop: the classic for loop with an index, the for...of loop, and the forEach method. Each has strengths depending on whether you need the index, the value, both, or the ability to exit early.

The Classic For Loop by Index

The most fundamental way to loop through an array uses a counter that doubles as the array index, giving you full control over which position you read from:

javascriptjavascript
const colors = ["red", "green", "blue"];
 
for (let i = 0; i < colors.length; i++) {
  console.log(`Index ${i}: ${colors[i]}`);
}

The condition keeps i below the array length, so it visits index 0, 1, and 2 and then stops before trying index 3. Output:

texttext
Index 0: red
Index 1: green
Index 2: blue

Each iteration reads colors[i], where i starts at 0 and increases by 1. The loop stops when i equals the array length, which is 3. Indices 0, 1, and 2 are accessed; index 3 is never reached.

The critical detail: < not <=

This is the most important rule for array loops:

javascriptjavascript
const items = ["a", "b", "c"];
 
// RIGHT: i < items.length
for (let i = 0; i < items.length; i++) {
  console.log(items[i]); // a, b, c
}
 
// WRONG: i <= items.length
for (let i = 0; i <= items.length; i++) {
  console.log(items[i]); // a, b, c, undefined
}

An array of length 3 has valid indices 0, 1, and 2. Using less-than-or-equal attempts to access index 3, which does not exist and returns undefined.

This off-by-one error is the single most common array loop bug. See the for loop syntax guide for more on the three-part header.

Modifying array elements

Because you have the index, you can change the original array as you iterate:

javascriptjavascript
const numbers = [1, 2, 3, 4];
 
for (let i = 0; i < numbers.length; i++) {
  numbers[i] = numbers[i] * 2;
}
 
console.log(numbers); // [2, 4, 6, 8]

Each element is doubled in place. The index gives you both read and write access to the array.

Looping backward

A for loop can iterate from the end to the beginning by counting down:

javascriptjavascript
const letters = ["x", "y", "z"];
 
for (let i = letters.length - 1; i >= 0; i--) {
  console.log(letters[i]);
}
// Prints: z, y, x

Start at the last index (length minus 1), stop at 0, and decrement. This is useful when removing items from an array while iterating, because removing from the end does not shift the indices of items you have not visited yet.

The for...of Loop

When you only need the values and do not care about the index, for...of is cleaner:

javascriptjavascript
const fruits = ["apple", "banana", "cherry"];
 
for (const fruit of fruits) {
  console.log(fruit);
}

There is no counter and no length check, so the loop simply visits each value in order and prints it. Output:

texttext
apple
banana
cherry

No counter, no index, no length check. The loop variable fruit gets assigned each array value in order. You can use const because a new binding is created for each iteration.

Getting the index with entries()

If you need both the value and the index with for...of, use .entries():

javascriptjavascript
const tools = ["hammer", "saw", "drill"];
 
for (const [index, tool] of tools.entries()) {
  console.log(`${index}: ${tool}`);
}

Array destructuring unpacks each index-and-tool pair into two separate variables in one step, so both the position and the value are available inside the loop body. Output:

texttext
0: hammer
1: saw
2: drill

.entries() returns an iterator of index-and-value pairs, which array destructuring unpacks into separate variables. This gives you the readability of for...of with the index access of a classic for loop.

Breaking and continuing

Unlike forEach, for...of supports break and continue:

javascriptjavascript
const scores = [72, 45, 88, 30, 95];
 
for (const score of scores) {
  if (score < 50) continue;
  console.log("Passing:", score);
  if (score > 90) break;
}
// Prints: Passing: 72, Passing: 88

The loop skips scores below 50 with continue and stops entirely when it finds one above 90 with break. This kind of control is impossible with forEach.

The forEach Method

forEach is an array method that calls a function once for each element:

javascriptjavascript
const pets = ["cat", "dog", "fish"];
 
pets.forEach((pet, index) => {
  console.log(`${index}: ${pet}`);
});

The callback runs once per element automatically, receiving the value and index as arguments without any manual counter or stop condition to manage. Output:

texttext
0: cat
1: dog
2: fish

The callback receives the current element, the index, and the full array as arguments. You can use whichever ones you need.

When forEach falls short

forEach does not support break or continue. Once it starts, it visits every element:

javascriptjavascript
// forEach has no way to stop early
[1, 2, 3, 4, 5].forEach((num) => {
  if (num > 3) {
    // break; // SyntaxError: not allowed
  }
  console.log(num);
});
// Prints all five numbers no matter what

If you need to exit early or skip iterations, use a for loop or for...of with break and continue.

Choosing the Right Approach

Choosing an array iteration method
ApproachIndex AccessBreak/ContinueModify OriginalAsync Friendly
for loopYes, by counterYesYesYes
for...ofVia .entries()YesYesYes
forEachYes, as 2nd argNoYesNo

The classic for loop gives you the most control. for...of gives you the cleanest syntax for value-only iteration. forEach works well in functional pipelines where you chain several array methods together.

For a deeper comparison of when to use each approach, see when to use for, for...of, and forEach. If you are working with objects instead of arrays, the same three approaches apply with a few key differences.

Practical Pattern: Building a New Array

A common pattern is looping through one array to build another:

javascriptjavascript
const prices = [10, 20, 30];
const discounted = [];
 
for (let i = 0; i < prices.length; i++) {
  discounted.push(prices[i] * 0.8);
}
 
console.log(discounted); // [8, 16, 24]

The loop reads each original price, applies the discount, and pushes the result into a new array. This is what .map() does under the hood, but writing it as a loop makes the step-by-step logic visible.

Practical Pattern: Finding an Element

Use a for loop when you need to stop as soon as you find a match:

javascriptjavascript
const users = [
  { name: "Alice", active: false },
  { name: "Bob", active: true },
];
let firstActive = null;
for (const user of users) {
  if (user.active) {
    firstActive = user;
    break;
  }
}

The loop exits as soon as it finds Bob, the first active user, so firstActive ends up holding that object. There is no need to check the remaining items, which is both clearer and faster than iterating the entire array with forEach.

Rune AI

Rune AI

Key Insights

  • Use for (let i = 0; i < array.length; i++) to loop by index.
  • Always use < array.length, not <=, to avoid off-by-one errors.
  • Use for...of when you only need values and want simpler syntax.
  • Use forEach for functional-style iteration when you do not need break or continue.
  • Use array.entries() with for...of to get both index and value.
RunePowered by Rune AI

Frequently Asked Questions

Which is better: for loop, for...of, or forEach?

It depends on what you need. Use for when you need the index or need to break/continue. Use for...of when you only need the values and want clean syntax. Use forEach when you prefer a functional style and do not need to break early.

How do I get the index when using for...of?

Use the .entries() method: for (const [index, value] of array.entries()). This gives you both the index and the value in each iteration.

Can I use await inside a forEach loop?

No, forEach does not wait for async operations. If you need to await inside a loop, use a for...of loop with async/await instead.

Conclusion

Looping through arrays is a fundamental JavaScript skill. The classic for loop gives you full control with indices, for...of provides clean value-only iteration, and forEach works well for functional pipelines. Understanding all three lets you pick the right approach for each situation.