A loop repeats a block of code — once per item in a list, once per second, or until some condition stops being true. JavaScript gives you several loop forms; the trick is picking the one that says most clearly what you’re trying to do.
for...of — looping over the values in a collectionThis is the loop you’ll reach for most often when you have an array (or any other collection of values) and want to do something with each item:
const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color);
}
// "red"
// "green"
// "blue"
It reads almost like English — “for [each] color of colors” — and it hands you each value directly, with no counter or indexing to manage.
for loopWhen you need the position of each item, or you’re not iterating over a
collection at all — just repeating something a fixed number of times — the
traditional three-part for loop is still the right tool:
for (let i = 0; i < 5; i++) {
console.log(`Attempt ${i + 1}`);
}
// "Attempt 1"
// "Attempt 2"
// ... up through "Attempt 5"
Breaking down the syntax — the parentheses hold three parts separated by semicolons:
let i = 0 — runs once, before the loop starts, to set up a counter.i < 5 — checked before every iteration; the loop continues as long
as this is true.i++ — runs after every iteration, here incrementing the counter by
one (i++ is shorthand for i = i + 1).while and do...while — looping until a condition changesUse while when you don’t know in advance how many times you’ll loop — only
that you should keep going while some condition holds:
let attempts = 0;
while (attempts < 3) {
console.log(`Trying... (${attempts + 1})`);
attempts++;
}
do...while is a small variation that always runs the body at least once,
checking the condition only afterward — handy for things like “ask the user
for input, and keep asking until they give a valid answer”:
let input;
do {
input = getNextInput(); // pretend this asks the user something
} while (!isValid(input));
break and continue — controlling a loop mid-flightInside any loop, break stops it immediately, and continue skips ahead to
the next iteration without finishing the current one:
const numbers = [4, 9, 15, 6, 2];
for (const number of numbers) {
if (number > 10) break; // stop entirely once we hit a big number
if (number % 2 !== 0) continue; // skip odd numbers
console.log(number);
}
// 4
for...infor...in loops over the keys of an object:
const user = { name: "Ada", role: "admin" };
for (const key in user) {
console.log(key); // "name", then "role"
}
It’s worth recognizing, but as the Objects lesson explains, Object.keys
(and Object.entries) are the more common modern choice for working with an
object’s properties — they avoid a quirk of for...in where it can also
visit inherited properties you didn’t intend to include.
Before for...of and array methods like .map/.forEach were common, every
loop over an array used a counter and the array’s .length:
var colors = ["red", "green", "blue"];
for (var i = 0; i < colors.length; i++) {
console.log(colors[i]);
}
This is the same classic for loop shown above, just aimed at an array
instead of a fixed count. It works, but it requires you to manage an extra
variable (i), index into the array yourself (colors[i]), and get the
start, stop, and step exactly right — a frequent source of subtle
“off-by-one” bugs (looping one time too many or too few).
for...of removes the counter and indexing entirely — you just say what you
want (“each color”) and let JavaScript handle the bookkeeping. That’s why
it, along with .map/.filter/.forEach from the Arrays lesson, has become
the default way to loop over collections, while the classic counting for
loop is reserved for the cases that genuinely need a counter or a fixed
number of repetitions.