When to use a "for" loop vs forEach

When to use a "for" loop vs forEach

Both the "for" loop and "forEach" loop serve different purposes and have their own strengths.

The forEach approach is ideal in scenarios where you simply need to iterate over array items and perform an action without the need for complex control flow.

You can't access the forEach method on things that are not arrays.

Simply put, the forEach method is specifically designed to work with arrays and is not available for objects or other data types.

On the other hand, a "for" loop statement is preferred when there is a need for complex control flow, such as:

  1. Can run a loop without needing to work with arrays
  2. Early loop termination
  3. Modifying the loop counter
  4. There are a few other specific scenarios

Early loop termination

If you need to exit the loop based on a specific condition, a "for" loop offers more flexibility.

For example, imagine you're searching for an item inside an array:

//List of Unsafe Passwords
let unsafePasswords = [
    "123456",
    "123456789",
    "12345",
    "qwerty",
    "password",
    "12345678",
    "111111",
    "123123",
    "1234567890",
    "1234567",
    "qwerty123",
    "000000",
    "1q2w3e",
    "aa12345678",
    "abc123",
    "password1",
    "1234",
    "qwertyuiop",
    "123321",
    "password123"  
];

const passwordStrength = document.querySelector(".password-strength");

passwordField.addEventListener("keyup", function (event) {
    // Check if password exists in the unsafe list using a for loop
    for (let i = 0; i < unsafePasswords.length; i++) {
      if (passwordField.value === unsafePasswords[i]) {
        passwordStrength.style.color = "red";
        passwordStrength.textContent = "You're using an unsafe password";
        break; // Exit loop after finding a match
      }
    }
  });

Don't worry if you don't understand the above code. We will work on it in detail in an upcoming module.

For now, just understand that we are taking a password as input from a user and checking if the password entered exists inside the unsafePasswords array or not.

If the password was indeed found inside the unsafePasswords array, we are using the break statement to exit the loop as soon as the target password is found, saving unnecessary iterations.

This break functionality is not directly available in forEach.

If you want to achieve the same logic by using forEach, you have to use something called a "try/catch" statement:

passwordField.addEventListener("keyup", function (event) {
 try {
   unsafePasswords.forEach(function (unsafePassword) {
     if (passwordField.value === unsafePassword) {
       // Throw the unsafe password to signal a match
       throw unsafePassword; 
     }
   });
 } catch (unsafePassword) {
   // Handle the thrown unsafe password
   passwordStrength.style.color = "red";
   passwordStrength.textContent = "You're using an unsafe password: " + unsafePassword;
 }
});

Again, don't worry if you don't understand the above code. We will work on it in detail in an upcoming module.

Anyway, the code with the "try/catch" statement and the forEach method looks much more complicated when compared to achieving the same functionality with a simple "for" loop and the break statement.

Modifying the loop counter

Sometimes, you might need to modify the loop counter variable within the loop itself.

While possible in forEach with additional tricks, it's more straightforward with a "for" loop:

// Skipping even elements in an array
let numbers = [1, 2, 3, 4, 5, 6, 7, 8];

for (let i = 0; i < numbers.length; i += 2) {
  console.log(numbers[i]);
}

So far, you have only seen about how to increment the loop counter by 1.

But in the above code, we are incrementing the loop counter by 2 to iterate only over odd-indexed items

This technique can be tedious to achieve within forEach.

Although forEach doesn't offer direct control over the loop like for loops, you can achieve the same functionality of skipping even elements using a combination of forEach and a conditional statement:

let numbers = [1, 2, 3, 4, 5, 6, 7, 8];

numbers.forEach(function(number, index) {
  // Check if index is even
  if (index % 2 === 0) {
    // Skip even elements by returning from the callback
    return;
  }
  console.log(number); // Print only odd-indexed array items
});

Just like a "for" loop, the forEach() have access to the current loop counter as an index parameter.

Using the index parameter, we can skip working with unnecessary items of an array.

Anyway, the above code looks much more complicated and takes more lines of code when compared to the "for" loop version:

// Skipping even elements in an array
let numbers = [1, 2, 3, 4, 5, 6, 7, 8];

for (let i = 0; i < numbers.length; i += 2) {
  console.log(numbers[i]);
}

Isn't it?

So, as I always say, pick the right tool for the right job.

Don't increase the complexity of your code just because you prefer one tool over another.

At the end of the day, the best choice depends on the specific requirements of your code and the desired level of control for your loop.

That's all I wanted to convey about "for" loops and "forEach" loops for now.

We will learn all these snippets and other unexplored concepts in detail when their needs come in real-world projects.

In the next lesson, we will perform a small challenge, and after that, we will understand NodeLists and start building some real-world components like Tabs, Galleries, etc.