for...of, for...in, break and continue

Loop over arrays and strings with for...of, over object keys with for...in, and control loops with break, continue and labels.

Lesson 16 of 56Beginner15 min read

The classic for (let i = 0; i < n; i++) loop from the for loops lesson can do anything, but most of the time you don't actually need the counter. You just want each item of an array, each letter of a word, or each key of an object. JavaScript has two shorter loops for exactly that: for...of for values and for...in for keys.

You also often need to change a loop's course partway through. When you find the item you were searching for, there's no point checking the rest, so you break out of the loop. When an item is invalid, you want to continue with the next one instead of stopping completely.

In this lesson you'll learn when to use for...of and for...in, the common mistake that mixes them up, how break and continue work in every kind of loop, how labels let you break out of nested loops, and how these loops compare with array methods such as forEach.

for...of: loop over values

JavaScript
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}
  • for...of gives you each value in turn.
  • It works with anything iterable: arrays, strings, Sets, Maps, NodeLists from querySelectorAll, and more.
  • Use const for the loop variable unless you need to reassign it inside the loop.
  • Need the index too? Use for (const [i, fruit] of fruits.entries()).

for...in: loop over object keys

JavaScript
const prices = { tea: 2.2, coffee: 2.8, cake: 3.5 };
for (const item in prices) {
  console.log(item, prices[item]);
}
  • for...in gives you each key (property name) of an object as a string.
  • Read the value with square brackets: prices[item].
  • Avoid for...in on arrays. It gives indexes as strings, can include extra properties, and isn't guaranteed to be in order in older code.
  • A modern alternative is for (const [key, value] of Object.entries(obj)).

break and continue

StatementWhat it does
breakStops the loop completely and jumps to the code after it
continueSkips the rest of this iteration and moves to the next one

Both work in for, for...of, for...in, while and do...while loops. break also ends a switch case. When loops are nested, break and continue only affect the innermost loop. To stop an outer loop, put a label in front of it and write break outer;.

Loops vs array methods

NeedLoopArray method
Do something with each itemfor...offorEach
Stop early when foundfor...of with breakfind, some, findIndex
Build a new arraypush inside a loopmap, filter
Use await insidefor...of worksforEach doesn't wait

forEach can't be stopped with break. If you need to stop early, use for...of or a method like find. You'll see more methods in array methods.

JavaScript Loop Control Syntax

Loop control

for (const item of array) { }
for (const char of "hello") { }
for (const [i, item] of array.entries()) { }
for (const key in object) { console.log(key, object[key]); }
for (const [key, value] of Object.entries(object)) { }

for (const n of nums) {
  if (n < 0) continue; // skip negatives
  if (n > 100) break;  // stop completely
}

JavaScript Loop Control Summary

  • for...of loops over values of arrays, strings, Sets, Maps and NodeLists.
  • for...in loops over the keys of an object; avoid it for arrays.
  • break stops a loop; continue skips to the next iteration.
  • Labels let break and continue target an outer loop.
  • forEach can't be stopped early, so use for...of or find when you need to.

JavaScript Loop Control Examples

Each example runs in the page. Edit the code and press Run to see what changes.

Example 1

for...of with arrays and strings

const scores = [72, 95, 58, 88];
let total = 0;
for (const score of scores) {
  total += score;
}
console.log("Average:", total / scores.length);

for (const [i, score] of scores.entries()) {
  console.log(`Test ${i + 1}: ${score}`);
}

let vowels = 0;
for (const letter of "javascript") {
  if ("aeiou".includes(letter)) vowels++;
}
console.log("Vowels:", vowels);
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 3 to 5Each score is added to the total without needing an index.
  2. Line 8entries() gives the index and the value together.
  3. Line 13Strings are iterable, so for...of gives each letter.
Example 2

for...in with an object

const stock = { apples: 12, pears: 0, plums: 7 };

for (const fruit in stock) {
  console.log(`${fruit}: ${stock[fruit]}`);
}

for (const [fruit, count] of Object.entries(stock)) {
  if (count === 0) console.log(`Reorder ${fruit}`);
}
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 3 to 4fruit is each key; stock[fruit] reads the value.
  2. Line 7Object.entries with for...of gives key and value pairs, which is often clearer.
Example 3

break, continue and labels

const orders = [12, -1, 30, 0, 999, 45];

for (const amount of orders) {
  if (amount <= 0) {
    console.log("skip invalid", amount);
    continue;
  }
  if (amount > 500) {
    console.log("suspicious order, stopping");
    break;
  }
  console.log("process", amount);
}

const grid = [[1, 2], [3, 4], [5, 6]];
search: for (const row of grid) {
  for (const cell of row) {
    if (cell === 4) {
      console.log("found 4");
      break search;
    }
  }
}
ConsoleEdit the code, then press Run or Ctrl+Enter
Line-by-line explanation
  1. Lines 4 to 7Invalid amounts are skipped and the loop carries on.
  2. Lines 8 to 11A suspicious order stops the loop; 45 is never processed.
  3. Line 16The label names the outer loop.
  4. Line 20break search leaves both loops at once.

Common JavaScript Loop Control Mistakes

for...in on an array

Don't
for (const i in ["a", "b"]) {
  console.log(i + 1); // "01", "11": i is a string
}
Do
for (const [i, letter] of ["a", "b"].entries()) {
  console.log(i + 1, letter);
}

for...of on a plain object

Don't
for (const value of { a: 1, b: 2 }) { } // TypeError: not iterable
Do
for (const value of Object.values({ a: 1, b: 2 })) { }

Trying to break out of forEach

Don't
items.forEach(item => {
  if (item === target) break; // SyntaxError
});
Do
for (const item of items) {
  if (item === target) break;
}

JavaScript Loop Control in Real Projects

Loops in real code

Shopping carts loop over items with for...of to total prices. Settings pages loop over object keys to build form fields. Search code uses break to stop once a match is found, and data import scripts use continue to skip blank or invalid rows instead of failing the whole file. DOM code loops over querySelectorAll results with for...of.

JavaScript Loop Control Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Loop over each colour's value.

const colours = ["red", "green", "blue"];
for (const colour  colours) {
  console.log(colour);
}
Predict the outputmedium

What is logged?

for (const n of [1, 2, 3, 4, 5]) {
  if (n === 2) continue;
  if (n === 4) break;
  console.log(n);
}
Multiple choiceeasy

What does for...in give you for an object?

Multiple choicemedium

Which loop can you stop early with break?

Fix the bugmedium

firstNegative should return the first negative number in the array, or null if there isn't one. Fix it.

function firstNegative(nums) {
  let found = null;
  for (const i in nums) {
    if (nums[i] < 0) {
      found = i;
      continue;
    }
  }
  return found;
}
console.log(firstNegative([4, -2, 7, -9]));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Returns the first negative value
  • Returns null when there is none
  • Works when the first item is negative

JavaScript Loop Control Quiz

5 questions to check what you learned.

  1. Which loop is best for the values of an array?

    • for...in
    • for...of
    • do...while
    • switch
  2. What does continue do?

    • Skips to the next iteration
    • Ends the program
    • Restarts the loop from the beginning
    • Exits all loops
  3. How do you get index and value in a for...of loop?

    • for (const i, v of arr)
    • for (const v in arr)
    • arr.indexOf inside the loop
    • for (const [i, v] of arr.entries())
  4. Which of these is NOT iterable with for...of?

    • A plain object
    • A string
    • A Set
    • A NodeList
  5. In nested loops, what does a plain break affect?

    • All loops
    • The outer loop
    • Only the innermost loop
    • Nothing

JavaScript Loop Control Challenge

Stock checker

Write checkStock(stock, limit):

  1. Loop over the keys of stock (an object like { tea: 3, milk: 0 })
  2. Skip items with a count of 0 using continue
  3. Collect the names of items with a count below limit into an array
  4. Stop the loop with break once the array has 3 names
  5. Return the array
function checkStock(stock, limit) {

}

console.log(checkStock({ tea: 3, milk: 0, sugar: 1, cups: 9, lids: 2, bags: 1 }, 5));
ConsoleEdit the code, then press Run or Ctrl+Enter
Checks
  • Finds low items, skipping zero
  • Stops at three names
  • Uses continue and break