EduFlow
JavaScript Fundamentals
0%

Section 2 · Logic and Functions

Loops: for, for…of and while

16 min4 min readCode playground

Lesson at a glance

Repeat work with for…of, the counting for loop and while, stop early with break and continue, and use the accumulator pattern to total a list of expenses.

  1. 1A list to loop over
  2. 2for…of: do this for each item
  3. 3The counting for loop
  4. 4while: repeat until something changes
  5. 5break and continue
  6. 6Seeing what a loop does

No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.

So far every Pocket example added up a fixed number of expenses: coffee + lunch + bus. Real spending is a list that grows every day. You cannot write + for items you do not have yet. You need a way to say “do this for each one”, and that is a loop.

A list to loop over

Lists get a full lesson in section 3, but you need the basics now. A list of values in square brackets is an array:

JavaScript
const amounts = [450, 1220, 270, 899];
console.log(amounts.length);  // how many items
console.log(amounts[0]);      // the first item: positions start at 0

for…of: do this for each item

for...of runs its block once per item, with a name of your choosing pointing at the current item:

JavaScript
const amounts = [450, 1220, 270, 899];

let total = 0;
for (const amount of amounts) {
  total += amount;
}
console.log(total);

Walk through it the way the engine does. total starts at 0. First pass: amount is 450, so total becomes 450. Second pass: amount is 1220, total becomes 1670. Then 1940, then 2839. There are no items left, so the loop ends and the next line logs the total.

This shape is called the accumulator pattern: declare a result before the loop, update it inside, use it after. It is behind totals, counts, maximums and almost every summary you will write. The const amount is fine even though it changes every pass: each pass creates a fresh amount, it is never reassigned.

for...of also works on strings, one character at a time: for (const ch of "Pocket").

The counting for loop

Sometimes you need the position as well as the item, for example to print “1. Coffee”. The classic for loop has three parts in its parentheses:

JavaScript
const labels = ["Coffee", "Lunch", "Bus"];

for (let i = 0; i < labels.length; i++) {
  console.log(`${i + 1}. ${labels[i]}`);
}
A for loop runs the start part once, then repeatedly checks the condition, runs the body, and runs the update, until the condition is false and the loop exits. let i = 0 i < labels.length? run the body i++ exit true false runs once
The three parts of a for loop and the order they run in

The start, let i = 0, runs once. Then, before every pass, the condition i < labels.length is checked; if it is true the body runs, then the update i++ adds one to i. When the condition becomes false the loop ends. With three labels, i takes the values 0, 1 and 2, exactly the valid indexes.

while: repeat until something changes

A while loop has only a condition. It is for situations where you know when to stop but not how many passes it will take. How many days can you keep buying a $4.50 coffee on a $20 budget?

JavaScript
let balance = 2000;
const coffee = 450;
let days = 0;

while (balance >= coffee) {
  balance -= coffee;
  days++;
}
console.log(`${days} coffees, ${balance} cents left`);

Each pass reduces balance, so the condition eventually becomes false. If nothing in the body moved toward the exit, for example if you forgot balance -= coffee, the condition would stay true forever. That is an infinite loop: the page freezes and the browser eventually offers to stop the script. When a tab hangs while you are practising, look for a loop whose condition never changes.

break and continue

Two keywords change a loop’s flow from inside:

  • break ends the loop immediately.
  • continue skips the rest of this pass and moves to the next one.
JavaScript
const amounts = [450, -300, 1220, 270, 899];
const budget = 2000;
let running = 0;

for (const amount of amounts) {
  if (amount < 0) {
    continue; // a refund: not spending, skip it
  }
  running += amount;
  if (running > budget) {
    console.log(`Budget passed at an expense of ${amount}`);
    break; // no need to look further
  }
}
console.log(running);

Trace it: 450 is added, then -300 is skipped, 1220 brings the total to 1670, 270 brings it to 1940, and 899 pushes it to 2839, which passes the budget, so the message is logged and the loop stops.

Seeing what a loop does

Loops are where beginners most often lose track of what the program is doing, because the same lines run many times with different values. The cure is to make the loop show you. Put a console.log at the top of the body that prints every variable involved:

JavaScript
const amounts = [450, 1220, 270];
let total = 0;
for (let i = 0; i < amounts.length; i++) {
  console.log({ i, amount: amounts[i], totalBefore: total });
  total += amounts[i];
}
console.log("final", total);

Each pass prints one line, so you can compare what actually happened with what you expected and find the first pass where they differ. That pass is where your bug is. Wrapping the values in { } prints them with their names, which saves you guessing which number is which. Professional developers do exactly this every day; in section 5 you will learn to do it with the DevTools debugger as well.

Loops and conditions together already let you write real logic. To reuse that logic instead of copying it, you need your own functions, which is the next lesson.

Key takeaways

  • for...of visits every item of a list in order and is the default loop for “do this for each expense”.
  • The counting for loop gives you an index, which you need when position matters; valid indexes run from 0 to length - 1.
  • while repeats as long as a condition is true, so something inside the loop must eventually make it false.
  • The accumulator pattern (start at 0, add inside the loop, use after the loop) turns a list into a single total.

Further reading

Check your understanding

4 questions

Question 1 of 4

What does this log?

JavaScript
const amounts = [400, 900, 250];
let total = 0;
for (const a of amounts) {
  total = a;
}
console.log(total);
Question 2 of 4

const days = ["Mon", "Tue", "Wed"]; Which loop throws no error but logs undefined once at the end?

Question 3 of 4

When is while a better fit than for...of?

Question 4 of 4

Inside a loop over expenses, what does continue do?

Practice

Code playground

Loop through Pocket's expenses

Each function receives amounts, an array of cents where negative numbers are refunds. Fill in:

  • totalSpent(amounts): the sum of all spending, skipping refunds.
  • countAtLeast(amounts, minimum): how many amounts are greater than or equal to minimum.
  • firstOverBudget(amounts, budget): the index of the expense at which the running total of spending first goes over budget (skip refunds), or -1 if it never does.
const amounts = [450, -300, 1220, 270, 899];

// Total of all spending; negative amounts are refunds, skip them
function totalSpent(amounts) {
  let total = 0;
  // loop here
  return total;
}

// How many amounts are at least `minimum`
function countAtLeast(amounts, minimum) {
  return 0;
}

// The index of the expense at which the running total of spending
// first goes over `budget`, or -1 if it never does (skip refunds here too)
function firstOverBudget(amounts, budget) {
  return -1;
}

console.log(totalSpent(amounts), countAtLeast(amounts, 500), firstOverBudget(amounts, 2000));
Loading the editor…

Ctrl/⌘ + Enter to run · Runs in a sandbox in your browser. Nothing leaves your device.

Console

(no output)

Checks

  • totalSpent adds spending and skips refunds
  • countAtLeast counts amounts at or above the minimum
  • firstOverBudget returns the index where the budget is first passed
  • firstOverBudget returns -1 when the budget is never passed