B Binance · The world's largest crypto exchangeBinance Sign up → AD OKX OKX · A leading global crypto exchangeOKX Sign up → AD
💻 Coding Basics · Lesson 4 / 10

Loops — Doing the Same Thing Many Times, Exactly

A loop states two things together: what to repeat and when to stop. Learn the two patterns for building totals and counts, plus the habit of checking the stop condition, and you can turn most repetitive work into code.

⏱ About 20 min ✍️ 5 practice questions 🧪 4 code exercises Updated 2026-10-09
🎯 By the end of this lesson you can
  • Choose between for, while and for...of to fit the situation
  • Use the running-total and counting patterns to get the value you need from a list
  • Control the flow of a loop with break and continue
  • Check stop conditions and boundary values to catch infinite loops and off-by-one mistakes

1.Why do we need loops?

In Lesson 1 we broke a program into sequence, conditions and repetition. If the conditionals of Lesson 3 are a fork in the road, the loops in this lesson are a road that circles back. To print 1 to 5 you could write five lines of console.log, but printing 1 to 1,000 is a different story. Copying and pasting lines invites mistakes, and changing a number means editing every line.

A loop lets you write, just once, "keep doing this while this condition holds." People get tired and make mistakes when they repeat the same task for a long time, but a computer does the hundredth repetition exactly like the first. On the other hand, a computer cannot decide on its own when to stop, so a person has to write the stopping condition precisely. Throughout this lesson we practice thinking of "what to repeat" and "when to stop" as a pair.

The code below produces the same result as five separate lines, using a single loop. Change the number 5 to 1000 and it prints 1,000 lines, yet the code changes by only a few characters. That is why loops are the starting point of automation.

The same task five times — in three lines of code
for (let i = 1; i <= 5; i++) {
  console.log('Greeting #' + i + ': Hello');
}
Output
Greeting #1: Hello
Greeting #2: Hello
Greeting #3: Hello
Greeting #4: Hello
Greeting #5: Hello

2.The `for` loop — a fixed number of repetitions

Inside the parentheses of a for loop are three parts separated by semicolons. The first is setup that runs only once (let i = 1), the second is a condition checked before every repetition (i <= 5), and the third is what happens at the end of each pass (i++). i++ is shorthand for i = i + 1. The body inside the curly braces runs while the condition is true, and the loop ends the moment the condition becomes false.

Knowing the exact order of execution matters. It goes setup → check condition → body → increment → check condition → body → increment …, and when the condition is false it skips the body and moves on to the code below the loop. That means at the end, i holds the first value that broke the condition. Writing down a variable's value line by line, as in the table below, is called tracing, and it is the first thing to try when a loop behaves strangely.

Naming the loop variable i is just an old convention, not a rule. If the meaning is clearer, use names like month or page. Because the loop variable changes, declare it with let, not const (Lesson 2).

The start of the 2 times table
const dan = 2;
for (let i = 1; i <= 4; i++) {
  console.log(dan + ' x ' + i + ' = ' + dan * i);
}
Output
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
2 x 4 = 8
Trace table for the code above — it stops the moment the condition is false
PassValue of `i`Condition `i <= 4`What happened
11trueprints 2 x 1 = 2, i becomes 2
22trueprints 2 x 2 = 4, i becomes 3
33trueprints 2 x 3 = 6, i becomes 4
44trueprints 2 x 4 = 8, i becomes 5
-5falseskips the body, loop ends

3.`for...of` and two basic patterns — running totals and counting

When you want to take the values out of a list one at a time, for...of is the easiest to read. Write for (const x of list) and the values of list go into x in order, from the first. Since you do not need to keep track of positions, you make fewer numbering mistakes. Lists (arrays) are covered in detail in Lesson 6; for now, just know that they are values separated by commas inside square brackets.

Much of what loops do comes down to two patterns. The running-total (accumulator) pattern creates an "empty so far" value before the loop, such as let sum = 0, and adds to it on every pass. The counting pattern starts with let count = 0 and adds 1 only when a condition is met. In both patterns the starting value matters: a sum starts at 0, a product starts at 1, and joining text starts with the empty string ''.

If you declare the accumulator inside the loop, it is reborn as 0 on every pass and the total never builds up. Always declare it outside the loop, above it. Conversely, the console.log that prints the result usually goes after the loop ends. Put it inside and the running total is printed on every pass. When you want to see intermediate values, you may put it inside on purpose for tracing.

Fictional sales records — the total (accumulating) and the number of sales of 10,000 won or more (counting)
const sales = [12000, 8500, 30000, 4000];
let sum = 0;
let count = 0;
for (const won of sales) {
  sum += won;
  if (won >= 10000) {
    count++;
  }
}
console.log('Total', sum);
console.log('10,000 won or more:', count);
Output
Total 54500
10,000 won or more: 2
ExampleYou want to compute the average of a fictional list of scores, [70, 85, 90, 60], with a loop. In what order should you think it through?
const scores = [70, 85, 90, 60];
let total = 0;
for (const s of scores) {
  total += s;
}
console.log(total / scores.length);
Output
76.25
  1. Step 1, what to accumulate: the sum of the scores. The starting value is 0.
  2. Step 2, the work of one pass: take one score and add it to the sum. 70 → 155 → 245 → 305.
  3. Step 3, after the loop ends: divide the sum 305 by the count 4. Get the count with scores.length.
  4. Check: 305 ÷ 4 = 76.25. It lies between 70 and 90, so it is plausible. An empty list would give 0 ÷ 0, which is NaN, so that case needs separate handling.
AnswerAccumulate the sum in a loop, then divide by the count after the loop: 76.25

4.The `while` loop and infinite loops — who changes the stop condition?

A while loop takes just one condition and keeps running the body while it is true. It fits well when you do not know in advance how many passes you need and must repeat "until the goal is reached." For example, how many months it takes to reach a savings goal by putting away the same amount each month can be found with a formula, but adding one month at a time and counting is the most intuitive way.

The question to always ask with while is: "Is there a line in the body that changes the condition?" In the code below, without saved += 50000, saved stays 0 forever and the condition stays true forever. That is an infinite loop. A program stuck in an infinite loop keeps running without any error message, so the browser tab seems to stop responding. The playground on this page forcibly stops code that does not finish within 2 seconds and reports a time limit.

There are three checks that prevent infinite loops. Does the variable in the condition change in the body? Does it change in the direction that makes the condition false (starting at 0 and only subtracting moves you away from the goal)? And did you use a condition like <, which also stops when you overshoot, instead of !==, which stops only on an exact match? As we saw with 0.1 + 0.2 in Lesson 2, decimals may never become exactly equal, so stopping on !== is risky.

A fictional savings plan — 50,000 won a month up to 300,000 won
const goal = 300000;
let saved = 0;
let months = 0;
while (saved < goal) {
  saved += 50000;
  months++;
}
console.log('After', months, 'months:', saved, 'won');
Output
After 6 months: 300000 won
If a loop misbehaves, put a console.log on the first line of the body that prints the loop variable and the accumulator. Once you can see which values appear after how many passes, the cause is usually obvious. If there are too many passes, temporarily make the condition smaller so you only see the first few.

5.`break` and `continue` — stopping early and skipping

break exits the loop immediately. When you only need the first value in a list that meets a condition, going all the way to the end after finding it is wasteful, so you stop with break. continue skips the rest of the current pass and moves on to the next one. Use it to filter out empty or invalid values and process only the rest.

Both keywords are handy, but overusing them makes the flow hard to follow. If a single loop mixes several break and continue statements, it is easier to read if you rewrite it with conditionals or split it into functions, which you will learn in Lesson 5. Inside a function in particular, return ends both the loop and the function at once, which shows the meaning "return as soon as you find it" more clearly.

Always think about the "not found" case too. In the first code below, found starts at -1 as a marker meaning "not found yet." If it is still -1 after the loop ends, no value in the list met the condition. The array method indexOf returning -1 when it finds nothing follows the same convention (Lesson 6).

break — find only the first one and stop (positions count from 0)
const temps = [3, 1, -2, 5, -4];
let found = -1;
for (let i = 0; i < temps.length; i++) {
  if (temps[i] < 0) {
    found = i;
    break;
  }
}
console.log('First below-zero position', found);
Output
First below-zero position 2
continue — skip the blanks and process the rest
const items = ['apple', '', 'pear', '', 'plum'];
for (const name of items) {
  if (name === '') {
    continue;
  }
  console.log(name);
}
Output
apple
pear
plum

6.Off-by-one — the most common mistake, wrong by exactly one

The most common loop bug is running one time too many or one time too few. It is called an off-by-one error. There are usually three causes: whether to start at 0 or 1, whether to use < or <= in the condition, and confusing "how many" with "the last number." Array positions count from 0, so the last position of an array of length 5 is 4, not 5.

Let's build intuition with the fence-post problem. If you put posts every 1 m along a 10 m fence, you need 11 posts, not 10. The number of gaps and the number of end points differ by one. In the same way, for (let i = 0; i < 5; i++) runs 5 times with 0, 1, 2, 3, 4; for (let i = 1; i <= 5; i++) runs 5 times with 1 to 5; and for (let i = 0; i <= 5; i++) runs 6 times with 0 to 5. They all contain a "5," but the counts differ.

The surest way to catch off-by-one errors is to test the boundary values yourself. Just as we checked the boundaries of conditionals in Lesson 3, always try a loop with zero items, one item, and the last item. If you loop over an array by position and overshoot by one with i <= arr.length, arr[i] becomes undefined on the last pass and the total turns into NaN. No error message appears, just a strange value, which makes it even harder to find. If you do not need positions, using for...of avoids this mistake altogether.

One character between <= and < — the extra slot is undefined, the total is NaN
const nums = [10, 20, 30];
let a = 0;
for (let i = 0; i <= nums.length; i++) {
  a += nums[i];
}
console.log('Overshot total', a);
let b = 0;
for (let i = 0; i < nums.length; i++) {
  b += nums[i];
}
console.log('Correct total', b);
Output
Overshot total NaN
Correct total 60
  • Does the result make sense when the list is empty (0 items)? Total 0, count 0, and the average handled separately
  • With only one value, does the loop run exactly once?
  • Is the last value processed? Check whether the condition is < or <=
  • Does the variable in the condition change in the body so that it eventually becomes false?
  • Is the accumulator declared outside the loop?

7.Reading and judging loops — when facing AI-written code

Ask an AI coding assistant to "sum this list" and you quickly get code with a loop in it. But you have to check for yourself whether that code runs correctly on your data. When reading a loop, look for just three things: what it prepares before the loop (the starting value), what it does in one pass (the body), and when it stops (the stop condition). If you can put each of these three into one sentence, you understand the code.

Next, trace it by hand with a small input. Feed in a list of about three values, write down the variables on each pass like the trace table above, and compare with the actual output. Also try an empty list and a one-item list. If the results differ, tell the AI specifically: "With this input I got this result, but I expected this." That makes fixing it much faster. Reading errors and narrowing down causes is covered in Lesson 8, and verifying AI-written code in Lesson 10.

📌 Key points

  • A loop is syntax that states "what to repeat" and "when to stop" as a pair
  • A fixed number of times: for; each value in a list: for...of; until a goal is reached: while
  • Accumulating: set a starting value before the loop (sum 0) and add to it; counting: add 1 only when a condition holds
  • A while loop without a line in the body that changes the condition is an infinite loop
  • < vs <=, starting at 0 vs 1 — test the boundaries with an empty list, one value and the last value

✍️ Practice questions

Answer first, then open "Answer and explanation".

Q1. How many times does the body of for (let i = 0; i < 5; i++) run?

⭕ Correct

❌ Not quite — see the explanation

Answer and explanation
Answer ② 5 times

The condition is true when i is 0, 1, 2, 3 and 4, so it runs 5 times. When i becomes 5, i < 5 is false and the loop ends.

Q2. Which of these is an infinite loop? (n starts at 0)

⭕ Correct

❌ Not quite — see the explanation

Answer and explanation
Answer ② while (n < 3) { n--; }

n-- decreases n, so it goes 0, -1, -2 … and keeps moving away from the target 3. Even with a line that changes the condition, the loop never stops if the direction is wrong.

Q3. In code that sums a list, what happens if you put let sum = 0; inside the loop body?

⭕ Correct

❌ Not quite — see the explanation

Answer and explanation
Answer ② It is recreated as 0 on every pass, so the total never builds up

Declared inside the body, a new sum is created as 0 on every pass. On top of that, the variable cannot even be seen outside the loop. Declare accumulators above the loop.

Q4. Which statement about break and continue is correct?

⭕ Correct

❌ Not quite — see the explanation

Answer and explanation
Answer ② break exits the loop, and continue skips only the current pass

break ends the loop immediately, and continue skips the rest of the body and moves to the next pass (in a for loop it goes through the increment i++ and then checks the condition). Both work in for, while and for...of.

Q5. Looping over an array of length 4 with for (let i = 0; i <= arr.length; i++) and adding arr[i] gives NaN. Explain why in one sentence.

Answer and explanation
Answer On the last pass i becomes 4, so it adds the nonexistent slot arr[4] (undefined).

Positions only go from 0 to 3. Adding undefined to a number gives NaN, and after that anything you add is still NaN. Change the condition to i < arr.length or use for...of.

🧪 Code lab

Write functions that use loops to find totals, counts and positions. Boundary tests such as empty lists and 0 are graded too, so think about those cases before you run your code.

Your code runs only inside an isolated sandbox in this browser and is never sent to a server. It has no network access and is stopped after 2 seconds. Edited code is saved only in this browser. Ctrl+Enter (⌘+Enter) runs it; Tab inserts two spaces (press Esc, then Tab, to move on).

JavaScript is off, so the code can't run here, but you can still read each task, its starter code, the automatic checks and a sample solution.

1Add 1 through n

Write a function sumTo(n) that takes a number n and uses a loop to return the sum from 1 to n. If n is 0, return 0. Example: sumTo(5) is 15.

Automatic checks
  • sumTo(5)expected 15
  • sumTo(1)expected 1
  • sumTo(0)expected 0
  • sumTo(100)expected 5050
💡 Hint

If you write the condition as i < n, the final n is left out. What should you write to include n?

Show a sample solution
function sumTo(n) {
  let sum = 0;
  for (let i = 1; i <= n; i++) {
    sum += i;
  }
  return sum;
}

2Count scores at or above a cutoff

Write a function countAtLeast(scores, cut) that takes an array of scores scores and a cutoff score cut, and returns how many scores are at or above the cutoff. For an empty array, return 0.

Automatic checks
  • countAtLeast([50,70,90], 70)expected 2
  • countAtLeast([], 60)expected 0
  • countAtLeast([60,60,59], 60)expected 2
  • countAtLeast([10,20], 100)expected 0
  • countAtLeast([0,0], 0)expected 2
💡 Hint

"At or above" includes equal values. Check the difference between > and >=.

Show a sample solution
function countAtLeast(scores, cut) {
  let count = 0;
  for (const s of scores) {
    if (s >= cut) {
      count++;
    }
  }
  return count;
}

3Find the position of the first negative number

Write a function firstNegative(nums) that returns the position (counting from 0) of the first negative number in the array nums. If there is no negative number or the array is empty, return -1. Once you find one, stop instead of continuing the loop.

Automatic checks
  • firstNegative([3,1,-2,5,-4])expected 2
  • firstNegative([-1,2])expected 0
  • firstNegative([1,2,3])expected -1
  • firstNegative([])expected -1
  • firstNegative([0,4,-7])expected 2
💡 Hint

Inside a function, return ends both the loop and the function at once. Put the "not found" return -1 after the loop ends.

Show a sample solution
function firstNegative(nums) {
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] < 0) {
      return i;
    }
  }
  return -1;
}

4Sum of the digits (while)

Write a function digitSum(n) with while that takes a non-negative integer n and returns the sum of its digits. Example: digitSum(1234) is 1+2+3+4 = 10. n % 10 is the last digit, and Math.floor(n / 10) is the number with the last digit removed.

Automatic checks
  • digitSum(1234)expected 10
  • digitSum(0)expected 0
  • digitSum(9)expected 9
  • digitSum(1000)expected 1
  • digitSum(99999)expected 45
💡 Hint

If you forget the line that shrinks n, you get an infinite loop. Check that the variable in the condition changes in the body.

Show a sample solution
function digitSum(n) {
  let sum = 0;
  while (n > 0) {
    sum += n % 10;
    n = Math.floor(n / 10);
  }
  return sum;
}

🤖 Try asking AI like this

Copy a prompt and replace the [ ] parts with your own situation. Don't take the answer on trust — check it against this lesson.

When you don't understand how a loop runs

Suppose the JavaScript loop below runs with the input [small example input]. Show me how the variables change on each pass as a trace table (pass, variables, condition true/false, what happened). Also point out the condition at the moment the loop ends. Code: [paste here]

When you want to verify loop code an AI gave you

Explain the starting value, body and stop condition of the following loop in one sentence each. Then make a table of boundary test inputs and expected results from the angles of an empty list, a single value, the last value and possible infinite loops. I will run them myself and compare. Code: [paste here]

When you need more loop practice

Make 5 JavaScript loop exercises (for, while, for...of, break, continue), from easiest to hardest. Be sure to include one running-total/counting pattern and one off-by-one trap, and use fictional data. Hide the answers, and when I send my code, grade it with boundary-value inputs.

🧰 Related tools

Tools for checking and tidying the JSON, regular expressions and text from this lesson. Don't paste real personal data or passwords.

References
  • MDN Web Docs — JavaScript Guide: Loops and iteration
  • MDN Web Docs — reference for the for, while, for...of, break and continue statements
  • General material on iteration statements in the ECMAScript Language Specification (ECMA-262)

Reached every goal above? Mark the lesson complete.

💻 Coding Basics

  1. 1What Is a Program? — Breaking Work into Sequence, Choice, and Repetition
  2. 2Values, Variables, and Types — Putting Name Tags on Values
  3. 3Conditionals — Taking Different Paths Depending on the Situation
  4. 4Loops — Doing the Same Thing Many Times, Exactly
  5. 5Functions — Splitting Work into Small Named Machines
  6. 6Arrays and Objects — Storing and Handling Data
  7. 7Strings and Text — Cutting, Finding and Replacing Characters
  8. 8Debugging and Reading Errors — Turning Red Text into Clues
  9. 9Simple Automation — Spreadsheet Math and Text Cleanup in Code
  10. 10Reading and Verifying AI-Written Code — Tests, Security, Licenses, Privacy
📚 Worth reading
📊Using AI for Spreadsheets, and Checking the Formulas→ 💻AI Coding Assistants: Security and Licence Risks→ 💬Practising Conversation in a Foreign Language with AI→ ⚙️Finding Work Tasks Worth Automating with AI→
← Foundations for the AI Era