Types of loops in JS
In JavaScript, loops split into condition statements (for, while, do...while) and iteration statements (for...in, for...of), with array methods such as forEach alongside them. The difference is what drives the repetition: a counter, a condition, the keys of an object, or the iterator of a collection.
Theory
TL;DR
foris the classic loop, used when the number of iterations is known in advance.whileis a pre-test loop: its body may never run at all.do...whileis a post-test loop: its body is guaranteed to run at least once.for...inwalks the enumerable keys of an object, inherited ones included, and does not guarantee order.for...ofwalks the values of iterables: arrays, strings,Set,Map,arguments.forEachis not a statement but an array method, andbreakandcontinuedo not work inside it.
Quick example
const numbers = [10, 20, 30];
for (let i = 0; i < numbers.length; i++) console.log(numbers[i]); // by index
for (const value of numbers) console.log(value); // by value
numbers.forEach((value, index) => console.log(index, value)); // array methodCounter and condition loops
1. for, the classic loop
Used when the number of iterations is known in advance.
for (let i = 0; i < 5; i++) {
console.log(i);
}Result:
0
1
2
3
4Structure:
for (initialization; condition; step) {
// loop body
}initializationruns once at the start;conditionis checked before every iteration;stepruns after every iteration.
2. while, the pre-test loop
Runs while the condition is truthy (true).
let i = 0;
while (i < 5) {
console.log(i);
i++;
}Use it when the number of iterations is not known in advance, for example while a queue is not empty, or until the server returns the last page.
3. do...while, the post-test loop
Guaranteed to run at least once, because the condition is checked after the body.
let i = 5;
do {
console.log(i);
i++;
} while (i < 5);Result:
5The body runs first, and only then is the condition checked.
Iteration statements
4. for...in, iterating object keys
Used to walk the properties of an object.
const user = { name: 'Tim', age: 25, city: 'Kyiv' };
for (const key in user) {
console.log(key, ':', user[key]);
}Result:
name : Tim
age : 25
city : KyivDetails:
- it visits every enumerable property, including ones inherited through the prototype;
- it does not guarantee order (integer-like keys come first, in ascending order);
- it is better not to use it for arrays: keys arrive as strings (
'0','1'), and foreign properties can show up alongside them.
5. for...of, iterating iterable objects
Ideal for arrays, strings, Set, Map and other iterable structures.
const numbers = [10, 20, 30];
for (const num of numbers) {
console.log(num);
}Result:
10
20
30It works with a string too:
for (const char of 'JS') {
console.log(char);
}Unlike for...in, it iterates values, not keys. If you also need the index, use for (const [i, value] of arr.entries()).
6. The forEach() method
It is not a statement but an array method, yet it does the same job: iteration.
const arr = ['a', 'b', 'c'];
arr.forEach((value, index) => {
console.log(index, value);
});Result:
0 a
1 b
2 cDetails:
- you cannot use
breakorcontinue, and areturninside the callback only ends the current iteration; - it is convenient for iteration with no early exit;
- it skips holes in sparse arrays;
- it sits next to
map,filter,reduce,someandevery, which return a result, whileforEachalways returnsundefined.
Comparison table
| Loop | What it iterates | When to use it | break / continue |
|---|---|---|---|
for | indexes, a counter | the iteration count is known | yes |
while | nothing, just a condition | the iteration count is unknown | yes |
do...while | nothing, just a condition | at least one pass is required | yes |
for...in | enumerable object keys | walking object properties | yes |
for...of | values of an iterable | arrays, strings, Set, Map | yes |
forEach | array elements | simple iteration with no exit | no |
Common mistakes
- Using
for...inon arrays: you get string keys and risk picking up inherited properties. Usefor...ofor a plainforfor arrays. - Expecting
breakto stop aforEach. It does not; if you need an early exit, usefor...of,someorfind. - Forgetting to advance the counter in a
whileand producing an infinite loop. - Confusing
do...whilewithwhile: the first always runs its body at least once, even when the condition is false from the start. - Declaring the counter with
varin a loop that has an asynchronous callback: every callback sees the same final value, becausevarhas no block scope. Uselet. - Calling
awaitinsideforEach: the method does not wait for promises, so you needfor...ofwithawait, orPromise.all.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.