In one of my first programming projects, I made a common beginner’s mistake while building a simple quiz game. For each question in the quiz, I copied and pasted the same block of code, changing only the question text and answers. This approach was absolutely tedious as it forced me to update every single copy of the code whenever I needed to change how the questions worked.
When I realized how inefficient this was, I went looking for a better solution and discovered loops. They seemed great as they allowed me to repeat tasks as many times as needed while keeping my code clean and organized. Once I understood how loops worked, I couldn’t imagine building programs without them.
In this article, I’ll walk you through the main types of loops in JavaScript. We’ll look at how each one works, when to use them, and how to choose the right one for your specific needs with examples based on real-world scenarios that you might encounter in your own projects.
Table of Contents
Other JavaScript Loop Alternatives (for-in and for-of)
What Are Loops in JavaScript?
I like to think of loops like a music playlist on repeat. They keep executing a block of code until a certain condition is met. Just as you might play your favorite playlist until you finish your workout, a loop continues running until the condition that has been set for its finalization is reached.
In real-world scenarios, you would use loops to perform repetitive tasks, such as processing items in a shopping cart, validating form fields, or updating game scores.
It’s easy to see why they are essential when you look at an e-commerce site where you’d need to:
- Calculate the total price of items in a cart
- Check if all required form fields are filled out
- Apply a discount to every item in a category
- Send confirmation emails to a list of customers
The for Loop
The first loop I truly understood was the for loop. It is arguably the most commonly used loop in JavaScript. You could think of it as your daily routine: you know exactly how many times you need to do something, when to start, and when to stop. For example, you know you need to brush your teeth twice a day. It’s a set number of repetitions with clear start and end points.
Let’s look at how a for loop works with a practical example. Imagine you’re building a shopping cart that needs to calculate the total price of all items:
// Shopping cart items with prices const cartItems = [ { name: “T-shirt”, price: 19.99 }, { name: “Jeans”, price: 49.99 }, { name: “Shoes”, price: 79.99 } ]; // Initialize total to 0 let total = 0; // Use a for loop to loop through each item in the cart for (let i = 0; i < cartItems.length; i++) { // Log the current item’s details console.log(`Adding ${cartItems[i].name} with price $${cartItems[i].price.toFixed(2)} to the total.`); // Add the price of the current item to the total total += cartItems[i].price; } // Log the final total console.log(`Total: $${total.toFixed(2)}`); |
I encourage you to try this code out in the browser’s console. The output should look like this:
Adding T-shirt with price $19.99 to the total. Adding Jeans with price $49.99 to the total. Adding Shoes with price $79.99 to the total. Total: $149.97 |
As you may have noticed in this example, the for loop has three key components:
- Initialization: let i = 0 — This sets the counter i to 0, starting at the first item in the list (index 0).
- Condition: i < cartItems.length — The loop runs as long as i is less than the total number of items. When i reaches the total, the loop stops.
- Update: i++ — After each iteration, i increases by 1, moving to the next item in the list.
Another real-world example is validating form fields. Let’s take a look:
// List of required form fields const formFields = [“email”, “password”, “username”]; // Array to store missing fields let missingFields = []; // Simulate form field values (replace these with actual DOM elements in real usage) const formValues = { email: “user@example.com”, password: “”, // Missing password username: “testuser” }; // Iterate through the required fields for (let i = 0; i < formFields.length; i++) { const fieldName = formFields[i]; const value = formValues[fieldName]; // Replace with actual DOM element value (e.g., document.getElementById(fieldName).value) // Log each field’s value console.log(`Checking field: ${fieldName}, Value: “${value}”`); // Check if the value is empty if (!value) { missingFields.push(fieldName); } } // Display missing fields if any if (missingFields.length > 0) { console.log(“Missing fields:”, missingFields.join(“, “)); alert(“Please fill in: ” + missingFields.join(“, “)); } else { console.log(“All fields are filled in!”); } |
If you try this out in the console, you will get this output:
Checking field: email, Value: “user@example.com” Checking field: password, Value: “” Checking field: username, Value: “testuser” Missing fields: password |
The while Loop
I personally discovered the power of while loops when I was working on my first game project. I needed to keep the game running until the player either won or lost. Using a for loop felt wrong since I didn’t know how many turns the game would take.
The while loop was perfect for this situation as, unlike the for loop where you know exactly how many times you need to repeat something, the while loop keeps running as long as a condition is true.
You could think of it as waiting for a bus, you’ll keep waiting until the bus arrives, but you don’t know exactly how many minutes that will be.
In another real-world scenario, a while loop would be useful to validate a user’s password input. Note that we are using prompt() here for demonstration purposes but in a real application you would typically use a secure form input field with validation both on the client and server sides to handle user credentials safely.
// Prompt user to create a password let password = prompt(“Create a password (minimum 8 characters):”); // Keep asking until the password meets the minimum length requirement while (password.length < 8) { console.log(`Entered password “${password}” is too short.`); alert(“Password too short! Try again.”); // Prompt again for a valid password password = prompt(“Create a password (minimum 8 characters):”); } // Log success once the password is valid console.log(`Password “${password}” successfully created`); alert(“Password created successfully!”); |
If you try it out in the console, you will be asked to provide a password. Let’s see what would happen if you entered “12345” and “mystrongpassword” as passwords:
Input: “12345” Console: Entered password “12345” is too short. Alert: Password too short! Try again. Input: “mystrongpassword” Console: Password “mystrongpassword” successfully created Alert: Password created successfully! |
Since we don’t know how many attempts the user will need to enter a valid password, the loop continues until they provide one that meets our requirements.
Another real-world scenario where we might use a while loop would be the implementation of a simple game turn system:
// Initialize player and enemy health let playerHealth = 100; let enemyHealth = 100; // Keep the game running as long as both are alive while (playerHealth > 0 && enemyHealth > 0) { // Player attacks the enemy let damage = Math.floor(Math.random() * 20) + 1; // Random damage between 1 and 20 enemyHealth -= damage; console.log(`Player hits enemy for ${damage} damage. Enemy health: ${enemyHealth > 0 ? enemyHealth : 0}`); // If enemy is still alive, it attacks back if (enemyHealth > 0) { damage = Math.floor(Math.random() * 15) + 1; // Random damage between 1 and 15 playerHealth -= damage; console.log(`Enemy hits player for ${damage} damage. Player health: ${playerHealth > 0 ? playerHealth : 0}`); } } // Log the game outcome console.log(playerHealth > 0 ? “Player wins!” : “Game Over!”); |
The output will be different every single time you execute this code because we are using Math.random() to generate random numbers but it should look something like this:
Player hits enemy for 18 damage. Enemy health: 82 Enemy hits player for 12 damage. Player health: 88 Player hits enemy for 15 damage. Enemy health: 67 Enemy hits player for 5 damage. Player health: 83 Player hits enemy for 20 damage. Enemy health: 47 Enemy hits player for 8 damage. Player health: 75 … Player hits enemy for 19 damage. Enemy health: 0 Player wins! |
The do-while Loop
The do-while is unique because it always executes the code block at least once before checking the condition. This makes it super useful when you need to run an instruction at least once no matter what.
You can think of it as a cooking recipe: you follow the initial steps and then decide if you need to make adjustments.
A good practical use case for a do-while loop would be the implementation of a game’s menu system. In this scenario, the menu will always be displayed at least once and will keep reappearing until the user selects the option to exit.
let userChoice; // Variable to store the user’s menu choice do { // Display the menu and prompt for a choice userChoice = prompt(` Choose an option: 1. Start New Game 2. Load Saved Game 3. Settings 4. Exit `); // Process the user’s choice using a switch statement switch (userChoice) { case “1”: console.log(“Starting new game…”); break; case “2”: console.log(“Loading saved game…”); break; case “3”: console.log(“Opening settings…”); break; case “4”: console.log(“Goodbye!”); break; default: // Handle invalid input console.log(“Invalid choice, please try again.”); } } while (userChoice !== “4”); // Repeat until the user selects “Exit” |
If you try this code example in the browser’s console, you’ll see the prompt keeps reappearing until you enter “4”. The selected options, along with any invalid entries, are logged to the console.
Input: “5” Console: Invalid choice, please try again. Input: “2” Console: Loading saved game… Input: “4” Console: Goodbye! |
Another common use case for the do-while loop is input validation that must happen at least once:
let userInput; // Variable to store the user’s input do { // Prompt the user for their age userInput = prompt(“Please enter your age (1-120):”); // Convert the input to a number userInput = Number(userInput); // Check if the input is invalid if (isNaN(userInput) || userInput < 1 || userInput > 120) { console.log(`Invalid input: ${userInput}. Please try again.`); } } while (isNaN(userInput) || userInput < 1 || userInput > 120); // Repeat until the input is valid // Log the verified age console.log(`Age verified: ${userInput}`); |
If you run this validation example and use the inputs you see below, the console would log the following:
Input: “abc” Console: Invalid input: NaN. Please try again. Input: “-5” Console: Invalid input: -5. Please try again. Input: “25” Console: Age verified: 25 |
Other JavaScript Loop Alternatives (for-in and for-of)
We’ve covered the three main types of loops but JavaScript also offers two more specialized loops: for-in and for-of. Both can improve your code performance and maintainability in specific situations, but they deserve their own detailed discussion.
For now, you should know that the for-of loop is perfect for iterating over arrays and other iterable objects in a cleaner way:
// An array of items const items = [‘apple’, ‘banana’, ‘orange’]; // Using a traditional for loop to iterate through the array for (let i = 0; i < items.length; i++) { // Log the current item by accessing it via its index console.log(items[i]); // Output: apple, banana, orange } // A cleaner alternative: using the for…of loop for (const item of items) { // Directly access each item in the array without needing an index console.log(item); // Output: apple, banana, orange } |
Both examples would log the same output to the console:
apple banana orange |
The for-in loop, however, is designed specifically for iterating over object properties:
const userProfile = { name: ‘John’, age: 30, role: ‘developer’ }; for (const property in userProfile) { console.log(`${property}: ${userProfile[property]}`); } |
In this case, the console would log the following:
name: John age: 30 role: developer |
Both of these loops are powerful tools for specific scenarios, but they work differently from traditional loops and come with their own set of considerations. If you’re interested in learning more about them, keep an eye out for an upcoming article focused on advanced loop techniques.
Choosing the Right Loop
Picking the right type of loop is like choosing the right tool for a home repair. You potentially would be able to get the job done with any of them but using the most appropriate one will make your life easier.
Table 1: When to choose each type of loop
Feature | For Loop | While Loop | Do-While Loop |
Best Used When | Known number of iterations, array processing | Unknown iterations, condition-based | Need at least one execution |
Use Cases | Array operations, counting, fixed repetitions | File processing, game loops, data streaming | Input validation, menu systems |
Iteration Control | Built-in counter | Manual counter if needed | Manual counter if needed |
Condition Check | Before first iteration | Before first iteration | After first iteration |
Tips for Selecting the Right Loop
Before I use a loop, I ask myself a few questions to make sure I’m using the most appropriate one for the task at hand:
How many times does the code need to run?
If there’s a clear count, I want to iterate a specific number of times, or I’m working with arrays, a for loop is usually the best choice. Its syntax is super clear and allows me to easily keep track of the index.
Am I waiting for something to happen?
while loops are perfect for those times when I don’t know how many iterations I’ll need, like when we need to wait for user input or process data until a certain condition is met.
Does the code need to run at least once?
If that’s the case then a do-while loop is definitely what I’d go for. This loop is particularly useful for menu systems or initial setup tasks where I want to ensure the code executes before checking any conditions.
Am I considering readability and performance?
Technically, all loops can achieve the same results but, as we’ve discussed before, some are more suitable for specific tasks. for loops are generally more efficient with arrays but do-while loops are generally better for user interactions.
// More efficient for large arrays for (let i = 0; i < hugeArray.length; i++) { // Length is calculated only once } // Less efficient let i = 0; while (i < hugeArray.length) { // Length is checked every iteration i++; } |
Also, I’d recommend you to always choose the loop that makes your code’s intention clear to other developers (including your future self). Always prefer readability over “smart”, elegant code.
// More readable for array operations for (let i = 0; i < array.length; i++) { array[i].process(); } // Less readable for the same task let i = 0; while (i < array.length) { array[i].process(); i++; } |
Wrapping Up
Choosing the right loop is about writing performant code that’s easy to understand and maintain. for loops are typically the most straightforward choice when working with arrays or known iterations, while loops excel at handling uncertain conditions, and do-while loops are perfect for situations where you need at least one execution.
If you’d like to master JavaScript loops and other essential programming concepts, you might want to check out Udacity’s Intermediate JavaScript Nanodegree program, where you’ll learn advanced programming concepts and best practices. Or, if you’re interested in building complete web applications, the Full Stack JavaScript Developer Nanodegree program will teach you how to create modern, scalable web applications from scratch.