JavaScript · Beginner
Loops in JavaScript: for, while, for...of and for...in
In short: A loop repeats a block of statements. A for loop counts with an index, a while loop runs until its condition becomes false, for...of visits each value of an array or string, and for...in visits an object's keys. break leaves a loop early and continue skips to the next round.
Repeating work
A loop runs the same block many times, either a known number of times, once per item of a collection, or until some condition changes. Choosing among JavaScript's loop statements is mostly a matter of which of those three you are asking.
The classic for loop has three parts in its header: an initialiser that runs once (let i = 0), a condition checked before every round (i < 5), and an update that runs after every round (i++). It is the loop for counting and for anything where you need the position. Declaring the counter with let in the header gives each round its own copy of the variable and keeps it out of the surrounding scope, which matters when a function inside the loop remembers it; the closures lesson shows why.
while (condition) checks the condition first and repeats the block as long as it stays true. The block must change something the condition depends on, or the loop never ends. It fits situations where the number of rounds is unknown: reading input until a sentinel line, halving a number until it is small. do { } while (condition) is the same but checks after the block, so the block always runs at least once.
for...of (ES2015) visits each value of an iterable, which includes arrays, strings, Maps and Sets. It is the loop to use when you have a collection and do not need the index, because there is no counter to get wrong. for...in visits the enumerable property keys of an object, as strings. It is for plain objects, not arrays: on an array it yields index strings such as "0" and can include inherited properties, so use for...of or a counted loop for arrays.
Two statements change the flow inside any loop. break ends the loop immediately and execution continues after it. continue abandons the current round and goes straight to the next condition check or the next item. Inside nested loops, both apply to the innermost loop only.
Reading input is where beginners meet loops first. readline() returns null when the input is exhausted, so while ((line = readline()) !== null) reads every line, and a for loop with a count read from the first line reads a known number of them.
Syntax
for (let i = 0; i < n; i++) { // init; condition; update
block;
}
while (condition) { // checked before each round
block; // must move toward making condition false
}
do {
block; // runs at least once
} while (condition);
for (const item of array) { } // each value of an array, string, Map, Set
for (const key in object) { } // each own enumerable key of an object
break; // leave the loop now
continue; // skip to the next round
let line;
while ((line = readline()) !== null) { // every line of input
block;
}The extra parentheses in (line = readline()) !== null are required: they make the assignment happen before the comparison.
Which loop when
| Situation | Loop |
|---|---|
| Repeat a known number of times, or need the index | for (let i = 0; ...) |
| Each value of an array or string, no index needed | for...of |
| Each key of a plain object | for...in (or Object.keys with for...of) |
| Repeat until a condition changes | while |
| Body must run at least once | do...while |
| Read input until it ends or a sentinel line arrives | while with readline() and break |
Counting with for: readings, an average and a countdown
Four temperature readings are visited by index, then a second loop counts down in steps of three.
const readings = [12.5, 13.25, 12.75, 14.5];
let total = 0;
for (let i = 0; i < readings.length; i++) {
total += readings[i];
console.log("Reading " + (i + 1) + ": " + readings[i]);
}
console.log("Average:", (total / readings.length).toFixed(2));
for (let n = 10; n > 0; n -= 3) {
console.log(n);
}Output
Reading 1: 12.5 Reading 2: 13.25 Reading 3: 12.75 Reading 4: 14.5 Average: 13.25 10 7 4 1
i runs from 0 to 3 because the condition i < readings.length stops it before 4; i + 1 is printed so the readings are numbered from one. total is an accumulator: it starts at 0 and each round adds one reading, the shape behind every sum and average. The second loop shows that the update can be any expression: n -= 3 gives 10, 7, 4, 1 and stops when n would be -2.
while and do...while
A savings plan runs until a target is reached; a do...while runs its block once even though its condition is false from the start.
let saved = 0;
let weeks = 0;
while (saved < 250) {
saved += 60;
weeks++;
}
console.log("Weeks needed:", weeks, "saved:", saved);
let n = 100;
let halvings = 0;
while (n > 5) {
n = n / 2;
halvings++;
}
console.log("Halved", halvings, "times, ending at", n);
let attempts = 0;
do {
attempts++;
console.log("Attempt", attempts);
} while (attempts < 1);Output
Weeks needed: 5 saved: 300 Halved 5 times, ending at 3.125 Attempt 1
The first loop has no way of knowing in advance how many rounds it needs; it keeps adding 60 until saved < 250 fails, which happens after the fifth week. The second halves 100 to 50, 25, 12.5, 6.25 and 3.125, five rounds, and stops because 3.125 is not greater than 5. The do...while block runs once and then tests attempts < 1, which is already false, so it ends; a plain while with the same condition would never have run the block at all.
Reading input until a sentinel, with continue, break, for...of and for...in
The input lines are 4, -2, 9, done and 7. Negative values are skipped and reading stops at the word done.
const kept = [];
while (true) {
const line = readline();
if (line === null || line === "done") {
break;
}
const value = Number(line);
if (value < 0) {
continue;
}
kept.push(value);
}
console.log("Kept:", kept);
for (const v of kept) {
if (v > 5) {
console.log("First value above 5:", v);
break;
}
}
const stock = { bolts: 40, nuts: 12 };
for (const key in stock) {
console.log(key + " -> " + stock[key]);
}
for (const ch of "ab") {
console.log(ch);
}Input given to the program: 4 ↵ -2 ↵ 9 ↵ done ↵ 7
Output
Kept: [ 4, 9 ] First value above 5: 9 bolts -> 40 nuts -> 12 a b
The first loop is written as while (true) because its exit test sits in the middle: it must read a line before it can decide whether to stop. Testing for null as well as "done" means the loop also ends safely if the sentinel never arrives. continue skips the push for -2 and goes back to the next readline(). The 7 after done is never read. The for...of loop leaves as soon as it finds 9, the for...in loop gives the keys of the object (and the value is fetched with stock[key]), and a string is iterable one character at a time.
Common mistakes
Looping with <= length
Why it goes wrong: Indexes run from 0 to
length - 1, sofor (let i = 0; i <= items.length; i++)visits one index too many and readsundefinedon the last round; arithmetic on it givesNaN.Fix: Use
i < items.length, or afor...ofloop that cannot go out of range.JavaScript · fixfor (let i = 0; i < items.length; i++) { console.log(items[i]); }A while loop whose condition never changes
Why it goes wrong:
while (count < 5) { console.log(count); }never incrementscount, so it prints forever and the program is killed by the runner's time limit.Fix: Make sure the block changes something the condition depends on, or switch to a counted
forloop when the number of rounds is known.Using for...in on an array
Why it goes wrong: It yields the indexes as strings, so
key + 1gives"01"rather than 1, and it can also visit properties added to arrays by libraries.Fix: Use
for...offor the values, or a countedforloop when you need numeric indexes.JavaScript · fixfor (const value of [10, 20]) { console.log(value); }Removing items from an array while looping over it by index
Why it goes wrong: Each removal shifts the later items one place left, so the item that followed the removed one is skipped.
Fix: Build a new array with
filter, or loop backwards from the last index so removals do not affect unvisited items.JavaScript · fixconst readings = [3, -1, 4, -2]; const positive = readings.filter((r) => r >= 0); console.log(positive); // [ 3, 4 ]
Where you use this
Nearly every exercise reads several lines of input, and a loop is how they are read. When the first line says how many follow, a counted for reads exactly that many; when the input simply ends, the while ((line = readline()) !== null) pattern reads until null. Inside the loop an accumulator collects the answer: a running total, a count of matches, the largest value seen so far, or an array of parsed values to process afterwards. Read, convert, update is the skeleton behind sums, averages and maximums in every language.
let line;
let count = 0;
let total = 0;
while ((line = readline()) !== null) {
total += Number(line);
count++;
}
console.log(count, total);Key points
for (let i = 0; i < n; i++)counts;for...ofvisits values;for...invisits object keys;whilerepeats until a condition fails.- Array indexes run from 0 to
length - 1, so the condition is<, not<=. - A
whilebody must change what the condition depends on, or it never ends. breakleaves the loop;continuejumps to the next round; both affect only the innermost loop.readline()returnsnullat the end of input; test for it to read every line.- Do not use
for...inon arrays and do not remove items from an array you are indexing through.
Try it yourself
The first input line says how many numbers follow. Read them in a loop and print the largest. The starter prints null until you fill in the loop.
const n = Number(readline());
let largest = null;
// read n numbers and keep the largest in largest
console.log(largest);
4 ↵ 8 ↵ 15 ↵ 3 ↵ 1115const n = Number(readline());
let largest = null;
for (let i = 0; i < n; i++) {
const value = Number(readline());
if (largest === null || value > largest) {
largest = value;
}
}
console.log(largest);
Practise this
Open the JavaScript playground
Related lessons
- Conditions in JavaScript: if, else if, else and switchHow if, else if, else and switch choose what runs in JavaScript, which values count as true, and how to write conditions that do what you meant.8 min
- JavaScript Arrays: Creating, Indexing and Changing ListsHow JavaScript arrays store ordered lists: indexing, length, push and pop, slice versus splice, sorting numbers correctly, and map, filter and reduce.10 min
- JavaScript Functions: Declarations, Arrows and Return ValuesHow to define and call JavaScript functions with declarations, expressions and arrow functions; parameters, default values, return and local scope.10 min
Frequently asked questions
What is the difference between for...of and for...in in JavaScript?
for...of iterates over the values of an iterable: the elements of an array, the characters of a string, the entries of a Map or Set. for...in iterates over the enumerable property names of an object, as strings, including names inherited from its prototype. Use for...of for arrays and strings and for...in (or Object.keys) for plain objects.
How do I get the index inside a for...of loop?
Loop over array.entries(), which yields index and value pairs: for (const [i, value] of array.entries()), using the array destructuring covered in the destructuring lesson. Alternatively, array.forEach((value, i) => ...) passes the index as the second argument, or use a counted for loop.
How do I read all input lines in JavaScript on this site?
Call readline() in a loop until it returns null: let line; while ((line = readline()) !== null) { ... }. If you prefer the whole input at once, readAll() returns the unread remainder as one string, which you can split on line breaks.
How this page was checked. Every program on it was run with Node.js 22 at build time; runs in your browser in an isolated Web Worker by the publishing checks, and the output shown is what it printed. The Run buttons execute the same code on your device; nothing you type is sent anywhere.