Learn by reading through in order

Looping on a Condition — while, do...while, break, and continue

Learn JavaScript's while and do...while: looping when you can't know the count in advance, avoiding infinite loops, and when to use continue vs. break.

Moving people off a waitlist as reservation slots open up, or buying more of something as long as your balance covers it — for tasks like these, you know when to stop, but you can't tell in advance how many times to repeat.

This article covers while and do...while, which repeat based on a condition, continue, which skips a pass, and break, which exits the loop.

Repeating Without a Fixed Count — while and Updating the Condition

Say some seats open up, and you want to move people up from the front of the waitlist in order. Each person you move up takes one seat, and you stop once there are 0 seats left. What stops the loop is a state — "while there are open seats" — not a number of passes, so a counting for loop doesn't express it naturally.

A while loop (a statement that repeats the body in curly braces as long as the condition in parentheses is true) takes only a condition in its parentheses. The condition is checked on every pass, before entering the body.

You set the starting value yourself before the loop, and you update the variable the condition checks yourself, inside the body.

const waitingList = ["Alice", "Bob", "Carol"];   // waitlist
let openSeats = 2;                                 // open seats

// Move people up only while there are open seats
while (openSeats > 0) {
  const name = waitingList.shift();
  openSeats--;   // same as openSeats = openSeats - 1
  console.log(`${name} moved up (seats left: ${openSeats})`);
}
// Alice moved up (seats left: 1)
// Bob moved up (seats left: 0)

console.log(`Still waiting: ${waitingList.length}`);   // Still waiting: 1
A while Loop That Ends vs. One That Doesn't
ConditionopenSeats > 0Body movessomeone upopenSeats--updatedAt 0, thecondition is falseConditionopenSeats > 0Body movessomeone upNo updateStays at 2,never ends
If the body decreases the variable the condition checks, the condition eventually becomes false and the loop ends. If it doesn't, the check gives the same result every time and the body keeps running.

In a for loop, the update expression has a fixed place inside the parentheses, but with while you decide where in the body to put it. The flip side of that freedom is that nothing stops you from forgetting it: the code is still perfectly valid without the update.

Forget the Update and the Loop Never Stops

If the condition never becomes false, the body repeats forever. If you forget to write openSeats--, the seat count stays at 2, so the check always gives the same result. The console shows a timeout after 15 seconds, but the loop doesn't stop, and the other exercises won't work either until you reload the page. Always change the variable the condition checks somewhere in the body.

Use a points balance to buy as many of the same item as you can. balance and unitPrice are already declared.

① Set up a variable, starting at 0, to count how many you've bought.

② Write the loop condition so it keeps repeating only while the balance covers one more item.

③ On each pass, decrease the balance, increase the count, and print "Item ◯ (points left: ◯)".

④ After the loop, print the number bought and the points left on one line.

(If it runs correctly, an explanation will appear.)

JavaScript / TypeScript Editor

Run code to see output

Running Once First — The Order of Checks in do...while

When a notification fails to send, you retry a few times until it succeeds. You have to send at least once before there's a result to check, but while checks its condition before entering the body, so depending on the starting value of the variable in the condition, the loop can end without sending anything.

A do...while loop (a statement that runs the body once and then checks the condition) is written as do { body } while (condition);, and everything up to the final semicolon is one statement. Since the check comes after the body, the body runs once even if the condition is false from the start.

const attempts = [false, false, true];   // send results prepared in advance (true means success)
let sent = true;                         // left over as true from the previous notification
let tried = 0;

// while checks first, so it ends without sending even once
while (!sent && tried < attempts.length) {
  sent = attempts[tried];
  tried++;
}
console.log(`Sends with while: ${tried}`);   // Sends with while: 0

// do...while sends the first time before checking, then uses the result to decide whether to continue
do {
  sent = attempts[tried];
  tried++;
  console.log(`Attempt ${tried}: ${sent ? "succeeded" : "failed"}`);
} while (!sent && tried < attempts.length);
// Attempt 1: failed / Attempt 2: failed / Attempt 3: succeeded
How while and do...while Differ at the Start
Starts withsent = trueChecks first!true is falseDoesn't enterthe bodySent 0 timesStarts withsent = trueBody first,sends attempt 1Result is false,!false continuesEnds on successat attempt 3
Both loops start with sent still true. while ends after just the check, while do...while sends once and then decides whether to continue.

Only the first pass skips the check; after that, the loop repeats only while the condition is true, just like while. If you don't want the body to run at all when the condition is false, choose while. If you want it to run once before you look at the result, choose do...while.

Assign the smallest unused booking number to a meeting-room reservation. The array usedNumbers, which holds the numbers already taken, is already declared.

① Set up a variable, starting at 0, to hold the number you'll assign.

② Using a loop that runs its body before checking, increase the number by 1 and print "Checking number ◯".

③ Write a condition that keeps repeating as long as the number is in the array of used numbers.

④ After the loop, print "Booking number: ◯".

JavaScript / TypeScript Editor

Run code to see output

Skipping Just One Pass — When to Use continue

When you go down a shipping list from the top, you'll want to skip any line that's out of stock and move on to the next. The more skip conditions you add, the deeper the if braces get, and the shipping code you actually care about ends up buried inside them.

With continue (a statement that skips the rest of the current pass and moves on to the next one), you can cut a pass short as soon as it hits a condition you want to skip. The loop itself keeps going, so the next pass starts normally with the condition check.

const names = ["A5 planner", "Desk lamp", "USB hub"];
const stocks = [12, 0, 5];   // 0 means out of stock
let index = 0;

while (index < names.length) {
  const name = names[index];
  const stock = stocks[index];
  index++;   // advance first so continue can't skip it

  // For out-of-stock lines, skip the rest of this pass and go to the next
  if (stock === 0) {
    console.log(`${name}: out of stock, skipped`);
    continue;
  }
  console.log(`${name}: shipping ${stock}`);
}
// A5 planner: shipping 12
// Desk lamp: out of stock, skipped
// USB hub: shipping 5
Line processedValue of stock and the checkResult of that pass
Line 1: A5 plannerstock is 12, not 0Prints shipping 12
Line 2: Desk lampstock is 0, so continueThe shipping line doesn't run
Line 3: USB hubstock is 5, not 0Prints shipping 5

continue skips only the lines between it and the end of the body. You can use continue in the body of for and for...of too, and since the update expression in a for loop's parentheses sits outside the body, it still runs on a pass that hit continue.

continue Also Skips Your Update Line

If you put index++ after continue, index doesn't advance on the skipped pass. The next pass reads the same line again, stock is still 0, the condition doesn't change, and the loop never ends. Update the variable the condition checks before continue.

Calculate the average of review scores, leaving out values that can't be counted. The array scores is already declared.

① Set up variables, starting at 0, for the total and the count.

② Use for...of to go through the scores one at a time.

③ For 0 (not rated) and any value greater than 5, print "Excluded ◯" and skip the rest of that pass.

④ Add the remaining scores to the total and the count, and after the loop print "Average: ◯.◯ (◯ reviews)".

JavaScript / TypeScript Editor

Run code to see output

Stopping as Soon as You Find It — Where break Takes You

Say you want to scan a log from the top and find only the first error. If you keep reading to the end after finding it, that's wasted work, and depending on how you write it, a later error can overwrite firstError.

With break (a statement that immediately ends the loop it's in), you can exit the loop on the pass where the condition is met. It's the same statement you used to exit a switch in the article on conditionals. You'll use the value you found outside the loop, so declare firstError before the loop.

const logs = ["INFO Started", "WARN Slow response", "ERROR Payment failed", "ERROR Resend failed"];
let index = 0;
let firstError = "";

while (index < logs.length) {
  const line = logs[index];
  index++;
  if (line.startsWith("ERROR")) {
    firstError = line;
    break;   // found the first one, so don't check the rest
  }
}

console.log(`First error: ${firstError}`);   // First error: ERROR Payment failed
console.log(`Lines checked: ${index}`);      // Lines checked: 3
The Curly Braces break Exits
while curly braces (check the log line by line)
  • const line = logs[index] — the line checked on this pass
  • After break, execution leaves the braces and moves on to the next console.log line
if curly braces (only lines starting with ERROR)
  • firstError = line — saves the line it found
  • break — exits the outer while, not these braces
  • Any lines below break never run
Neither the body lines below break nor the remaining passes run. Execution continues on the line after the while loop's closing brace.

Even on the pass that hits break, the index++ written before it has already run. So index stops at 3, and the "Lines checked: 3" printed after the loop matches the position of the line that was found, counting from 1.

Where continue and break Part Ways
continue whenstock === 0Checks index < 3againMoves on to theUSB hub passPrintsshipping 5break at thefirst ERROR lineDoesn't checkindex < 4Doesn't read theERROR on line 4Goes to the lineprinting the error
Neither one runs the rest of the lines in that pass. continue goes back to the condition check; break leaves the loop without checking.

Allocate stock to orders in the order they were received, and stop at the first order there isn't enough stock for. orderQuantities (the quantity for each order) and stock (the stock count) are already declared.

① Use for...of to go through each order's quantity one at a time.

② On a pass where the quantity is more than the stock, print "Not enough stock for an order of ◯" and end the loop.

③ On a pass where there's enough, decrease the stock and print "Allocated ◯ (◯ left)".

④ After the loop, print "Remaining stock: ◯".

JavaScript / TypeScript Editor

Run code to see output
QUIZ

Knowledge Check

Answer each question one by one.

Q1If a while loop starts with its condition true and the body never changes the variable the condition checks, what happens?

Q2If the condition is false from the start, how many times does the body of a do...while run?

Q3What happens next when continue runs inside a loop?