The Right Tool for the Job: An In-Depth Look at JavaScript Array Loops

25/09/2025

When you first start learning to code, you quickly get introduced to the classic for and while loops. But as you dig deeper into JavaScript, you discover there are many newer, "fancier" ways to iterate over an array. If you're like me, you've probably wondered: "Why are there so many options, and when should I use which one?"

I learned this the hard way when I tried to jump back and forth in an array using for…of with Array.entries() as I was trying to impress at an interview, just to find out that it wasn’t working as I expected.

I fumbled. I tried to manipulate the index inside the for...of loop (index = index + value), but the iterator just kept moving forward, ignoring my assignment. I panicked because I realized I overcomplicated. And in the end, I had to start from scratch with another solution.

After the interview I still had this question in the back of my mind: "Why didn't it work?" So I went back to the docs to find my answer.

In this article, we'll explore the nuances of each iteration method, clarifying their ideal use cases and highlighting the key distinction between direct index control and sequential traversal.

Statements vs. Expressions: A Core JavaScript Concept

The behavior of different iteration methods is tied to a fundamental concept of JavaScript: the difference between a statement and an expression.

*This distinction is crucial because it determines where you can use a piece of code. Contexts like the curly braces {} in React's JSX expect an expression to render, which is a key reason why .map() is the preferred method for creating lists.

Quick Reference

Looping Methods: Strengths and Limitations

For a concrete example, we will use a common data structure: an array of objects and we will breakdown each looping method with a common goal - finding the "Keyboard" and stopping.

const products = [
  { id: 1, name: "Laptop", price: 1200 },
  { id: 2, name: "Mouse", price: 25 },
  { id: 3, name: "Keyboard", price: 75 },
  { id: 4, name: "Monitor", price: 300 },
  { id: 5, name: "USB Hub", price: 15 },
];

1. The Classic for Loop: The Power of Manual Control

The classic for loop is a statement that provides complete control over the iteration process. You can access the index, modify the counter (i), and jump, skip, or reverse direction at any point. This makes it ideal for complex or conditional traversal logic , giving you the possibility to break at any time.

for (let i = 0; i < products.length; i++) {
  console.log(`Processing item ${i}: ${products[i].name}`);
  if (products[i].name === "Keyboard") {
    console.log("Keyboard found! Breaking the loop.");
    break;
  }
}
// Output:
// Processing item 0: Laptop
// Processing item 1: Mouse
// Processing item 2: Keyboard
// Keyboard found! Breaking the loop.

2. The while Loop: Another Form of Manual Control

Similar to the for loop, the while loop is a statement that offers full control over the index. The primary difference is in syntax and structure - it's often used when the number of iterations isn't known beforehand. Like the for loop, it is perfect for scenarios requiring precise control over the flow,including the ability to break.

let i = 0;
while (i < products.length) {
  console.log(`Processing item ${i}: ${products[i].name}`);
  if (products[i].name === "Keyboard") {
    console.log("Keyboard found! Breaking the loop.");
    break;
  }
  i++;
}
// Output:
// Processing item 0: Laptop
// Processing item 1: Mouse
// Processing item 2: Keyboard
// Keyboard found! Breaking the loop.

3. forEach(): The Simple, Forward-Only Loop

The forEach() method call is an expression that is a clean, readable way to execute a function for each element in an array. However, you can't use break to exit the loop early, nor can you skip elements or jump to a specific index. It is designed for straightforward, complete traversal.

products.forEach((product, i) => {
  console.log(`Processing item ${i}: ${product.name}`);
  if (product.name === "Keyboard") {
    console.log("Keyboard found! Cannot break the loop.");
    // No `break` or `return` will stop the forEach() loop.
  }
});
// Output:
// Processing item 0: Laptop
// Processing item 1: Mouse
// Processing item 2: Keyboard
// Keyboard found! Cannot break the loop.
// Processing item 3: Monitor
// Processing item 4: USB Hub

4. for...of: The Modern Iterator

The for...of loop is the modern standard for iterating directly over the values of an iterable object like an array. It is highly readable and safe, but fundamentally different from a for loop. It’s forward-only: you can’t skip, jump, or reverse direction, because it relies on the iterator protocol, which only provides the next value in sequence. However, a key advantage over forEach() is that it does support break and continue.

for (const product of products) {
  console.log(`Processing: ${product.name}`);
  if (product.name === "Keyboard") {
    console.log("Keyboard found! Breaking the loop.");
    break;
  }
}
// Output:
// Processing: Laptop
// Processing: Mouse
// Processing: Keyboard
// Keyboard found! Breaking the loop.

5. .entries(), .keys(), .values(): Unpacking the Iterator

These methods (.entries(), .keys(), .values()) return an iterator object. When used with a for...of loop, they allow you to access different aspects of the array. The .entries() method, for example, returns a pair of [index, value], which can be destructured for easy access. However, the core behavior remains: the iteration is strictly forward.

for (const [i, product] of products.entries()) {
  console.log(`Processing item ${i}: ${product.name}`);
  if (product.name === "Keyboard") {
    console.log("Keyboard found! Breaking the loop.");
    break;
  }
}
// Output:
// Processing item 0: Laptop
// Processing item 1: Mouse
// Processing item 2: Keyboard
// Keyboard found! Breaking the loop.

6. The .map() Method: Transforming Arrays

The .map() method is an expression that's designed to transform an array and return a new one of the exact same length. Its purpose is to process every single element in the original array, so you cannot use break to exit the loop early. This makes it perfect for creating a new array without modifying the original.

//Use .map() to create a new array with just the product names

const productNames = products.map(product => product.name);
console.log(productNames);

// Output:
// ["Laptop", "Mouse", "Keyboard","Monitor","USB Hub"]

The Fundamental Difference: Manual Index vs. Sequential Traversal

The key distinction between these methods is how they control iteration:

When to Use What

Final Thought: Every Mistake is a Step Forward

What you perceive as failure is just feedback. Every bug, every mistake, is a chance to learn something new. That interview didn’t go as planned, but it taught me something every developer should remember:

Next time you hit a wall, ask yourself:

By understanding these distinctions, you can write code that is not only functional but also clear, efficient, and well-suited to its task. Sometimes, the answer is a humble for loop. And that’s okay.