Docs

README

4.4 While and Do-While Loops

Overview

While loops and do-while loops execute a block of code as long as a condition remains true. Unlike for loops, they don't have built-in initialization or update expressions, making them ideal for situations where the number of iterations isn't known in advance.


Table of Contents

  1. While Loop
  2. Do-While Loop
  3. Comparison: While vs Do-While
  4. When to Use Each
  5. Common Patterns
  6. Loop Control
  7. Converting Between Loop Types
  8. Best Practices
  9. Common Pitfalls

While Loop

The while loop checks the condition before each iteration.

Syntax

while (condition) {
  // code to execute while condition is true
}

Flow Diagram

        ┌──────────────────┐
        │  Check Condition │ ◄───────────────┐
        └────────┬─────────┘                 │
                 │                           │
         ┌───────┴───────┐                   │
         │               │                   │
      [true]          [false]                │
         │               │                   │
         ▼               ▼                   │
    ┌─────────┐     Exit Loop                │
    │ Execute │                              │
    │  Body   │──────────────────────────────┘
    └─────────┘

Basic Example

let count = 0;

while (count < 5) {
  console.log(count);
  count++;
}
// Output: 0, 1, 2, 3, 4

Key Characteristics

FeatureDescription
Condition CheckBefore each iteration
Minimum Iterations0 (may never execute)
InitializationMust be done before the loop
UpdateMust be done inside the loop

Do-While Loop

The do-while loop checks the condition after each iteration, guaranteeing at least one execution.

Syntax

do {
  // code to execute at least once
} while (condition); // Note the semicolon!

Flow Diagram

    ┌─────────────────┐
    │ Execute Body    │ ◄───────────────┐
    │ (at least once) │                 │
    └────────┬────────┘                 │
             │                          │
    ┌────────▼────────┐                 │
    │ Check Condition │                 │
    └────────┬────────┘                 │
             │                          │
     ┌───────┴───────┐                  │
     │               │                  │
  [true]          [false]               │
     │               │                  │
     │               ▼                  │
     │          Exit Loop               │
     └──────────────────────────────────┘

Basic Example

let count = 0;

do {
  console.log(count);
  count++;
} while (count < 5);
// Output: 0, 1, 2, 3, 4

Executes At Least Once

let x = 10;

// While loop - never executes because condition is false
while (x < 5) {
  console.log('while:', x);
  x++;
}
// No output

// Do-while loop - executes once even though condition is false
do {
  console.log('do-while:', x);
  x++;
} while (x < 5);
// Output: "do-while: 10"

Comparison: While vs Do-While

Featurewhiledo-while
Condition CheckBefore iterationAfter iteration
Minimum Executions01
Use CaseMay not need to runMust run at least once
SemicolonNot requiredRequired at end

Side-by-Side Example

// Both produce the same output when condition is initially true

// While loop
let i = 0;
while (i < 3) {
  console.log('while:', i);
  i++;
}

// Do-while loop
let j = 0;
do {
  console.log('do-while:', j);
  j++;
} while (j < 3);

// Both output: 0, 1, 2

When to Use Each

Use while When:

  1. You might not need to iterate at all
// Processing might be empty
while (queue.length > 0) {
  processItem(queue.shift());
}
  1. The condition determines whether to start
let input = getInput();
while (input !== 'quit') {
  process(input);
  input = getInput();
}
  1. Unknown number of iterations
let target = 1000;
let current = 1;
while (current < target) {
  current *= 2;
}

Use do-while When:

  1. You need at least one execution
let userInput;
do {
  userInput = prompt('Enter a number (1-10):');
} while (userInput < 1 || userInput > 10);
  1. Menu-driven programs
let choice;
do {
  displayMenu();
  choice = getChoice();
  executeChoice(choice);
} while (choice !== 'exit');
  1. Validation after action
let attempts = 0;
do {
  attempts++;
  result = tryConnection();
} while (!result.success && attempts < 3);

Common Patterns

1. User Input Validation

function getValidAge() {
  let age;
  do {
    age = parseInt(prompt('Enter your age (0-120):'));
  } while (isNaN(age) || age < 0 || age > 120);
  return age;
}

2. Reading Until Condition

// Read lines until empty
const lines = [];
let line = readline();

while (line !== '') {
  lines.push(line);
  line = readline();
}

3. Waiting for Condition

// Wait for element to appear (with timeout)
let element = null;
let attempts = 0;
const maxAttempts = 10;

while (!element && attempts < maxAttempts) {
  element = document.querySelector('#myElement');
  attempts++;
  if (!element) {
    await sleep(100); // Wait 100ms
  }
}

4. Game Loop

let gameRunning = true;

while (gameRunning) {
  handleInput();
  updateGameState();
  render();

  if (isGameOver()) {
    gameRunning = false;
  }
}

5. Random Number Generation

// Generate random numbers until getting one above threshold
let randomNum;
let attempts = 0;

do {
  randomNum = Math.random();
  attempts++;
} while (randomNum < 0.9);

console.log(`Got ${randomNum} after ${attempts} attempts`);

6. Collatz Conjecture (3n+1 Problem)

function collatzSteps(n) {
  let steps = 0;

  while (n !== 1) {
    if (n % 2 === 0) {
      n = n / 2;
    } else {
      n = 3 * n + 1;
    }
    steps++;
  }

  return steps;
}

console.log(collatzSteps(27)); // 111 steps

7. Binary Search

function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }

  return -1; // Not found
}

8. Processing Queue

const taskQueue = ['task1', 'task2', 'task3'];

while (taskQueue.length > 0) {
  const task = taskQueue.shift();
  console.log(`Processing: ${task}`);

  // Task might add new tasks
  if (task === 'task1') {
    taskQueue.push('task1-subtask');
  }
}

Loop Control

break - Exit Immediately

let i = 0;
while (true) {
  // Infinite loop
  console.log(i);
  i++;
  if (i >= 5) {
    break; // Exit the loop
  }
}
// Output: 0, 1, 2, 3, 4

continue - Skip to Next Iteration

let i = 0;
while (i < 10) {
  i++;
  if (i % 2 === 0) {
    continue; // Skip even numbers
  }
  console.log(i);
}
// Output: 1, 3, 5, 7, 9

Labeled Statements

outer: while (true) {
  let inner = 0;
  while (inner < 5) {
    inner++;
    if (inner === 3) {
      break outer; // Break out of outer loop
    }
    console.log(`inner: ${inner}`);
  }
}
// Output: inner: 1, inner: 2

Converting Between Loop Types

For Loop to While Loop

// For loop
for (let i = 0; i < 5; i++) {
  console.log(i);
}

// Equivalent while loop
let i = 0;
while (i < 5) {
  console.log(i);
  i++;
}

While Loop to For Loop

// While loop
let count = 10;
while (count > 0) {
  console.log(count);
  count--;
}

// Equivalent for loop
for (let count = 10; count > 0; count--) {
  console.log(count);
}

Do-While to While

// Do-while loop
let x = 0;
do {
  console.log(x);
  x++;
} while (x < 5);

// Equivalent while loop (execute first, then loop)
let y = 0;
console.log(y); // First execution
y++;
while (y < 5) {
  console.log(y);
  y++;
}

Best Practices

1. Ensure Loop Termination

// ✅ Good: Condition will eventually be false
let i = 0;
while (i < 10) {
  console.log(i);
  i++; // Always update toward termination
}

// ❌ Bad: Potential infinite loop
let j = 0;
while (j < 10) {
  console.log(j);
  // Forgot to increment j!
}

2. Use Meaningful Conditions

// ✅ Good: Clear condition
while (itemsRemaining > 0) {
  processNextItem();
  itemsRemaining--;
}

// ✅ Good: Named function
while (hasMoreItems()) {
  processNextItem();
}

// ❌ Less clear
while (x) {
  // What does x represent?
}

3. Avoid Complex Conditions

// ❌ Complex and hard to read
while (a > 0 && b < 100 && !done && attempts < maxAttempts) {
  // ...
}

// ✅ Better: Extract to function
function shouldContinue() {
  return a > 0 && b < 100 && !done && attempts < maxAttempts;
}

while (shouldContinue()) {
  // ...
}

4. Add Safety Limits

// Add a maximum iteration count to prevent infinite loops
const MAX_ITERATIONS = 1000;
let iterations = 0;

while (someCondition && iterations < MAX_ITERATIONS) {
  // Process
  iterations++;
}

if (iterations >= MAX_ITERATIONS) {
  console.warn('Loop hit maximum iterations');
}

Common Pitfalls

1. Infinite Loops

// ❌ Missing update
let i = 0;
while (i < 5) {
  console.log(i);
  // i never changes - infinite loop!
}

// ❌ Wrong update direction
let j = 10;
while (j > 0) {
  console.log(j);
  j++; // j increases, never < 0
}

// ❌ Condition never becomes false
let k = 1;
while (k !== 0) {
  k = k / 2; // Gets very small but never exactly 0
}

2. Off-By-One Errors

// ❌ Wrong: Runs 6 times (0-5)
let i = 0;
while (i <= 5) {
  console.log(i);
  i++;
}

// ✅ Correct: Runs 5 times (0-4)
let j = 0;
while (j < 5) {
  console.log(j);
  j++;
}

3. Forgetting the Semicolon in Do-While

// ❌ Syntax error
do {
  console.log('Hello');
} while (false); // Missing semicolon!

// ✅ Correct
do {
  console.log('Hello');
} while (false);

4. Variable Scope Issues

// ❌ Variable declared inside loop - created each iteration
while (condition) {
  let counter = 0; // Resets to 0 each time!
  counter++;
}

// ✅ Variable declared outside loop
let counter = 0;
while (condition) {
  counter++;
}

Summary

Featurewhiledo-while
Checks conditionBefore bodyAfter body
Minimum runs01
SemicolonNot requiredRequired
Best forUnknown iterationsAt least one run

Quick Reference

// While - may not execute
while (condition) {
  // code
}

// Do-while - executes at least once
do {
  // code
} while (condition);

Next Steps

  • Practice with the examples in examples.js
  • Complete the exercises in exercises.js
  • Learn about for...of and for...in loops
  • Explore array methods as alternatives to loops
README - JavaScript Tutorial | DeepML