So far a program runs straight down the page, one line after another. Control flow is what lets it make decisions and repeat work instead, which is where code starts to feel genuinely useful. There are two halves to it. Conditional statements choose which code to run based on a test, and loops run the same code many times. This article covers both: if/else and switch for branching, the for, while, and do-while loops for repetition, the for-in and for-of loops for stepping through objects and arrays, and the break and continue keywords for steering a loop from the inside. It finishes with a worked example that puts several of them together.
I prepared for you 10 code snippets related to this lesson here: https://datalad.co.uk/javascript-control-flow-and-loops-code-along-workbook/
What I recommend is for you to read the theory below, and then try to just write yourself those code snippets. Muscle memory is real.
Making decisions with if, else if, and else
The most basic decision is an if statement: run a block of code only when a condition is true. Chain it with else if to test further conditions, and else to catch everything that did not match. Here we greet the user differently depending on the hour.
let hour = 10;if (hour >= 6 && hour < 12) { console.log('Good morning');} else if (hour >= 12 && hour < 18) { console.log('Good afternoon');} else { console.log('Good evening');}
The conditions are checked from top to bottom, and the first one that is true wins, after which the rest are skipped. So with the hour set to ten, the first condition matches and “Good morning” prints, and nothing else is even evaluated. Notice the logical AND from the operators article doing real work here, combining two comparisons into a single range test. The curly braces group the code that belongs to each branch, and while you can omit them for a single line, keeping them always is a good habit that prevents a whole category of bugs.
Choosing among many values with switch
When you are comparing one variable against many possible exact values, a long else if chain gets repetitive, and switchexpresses it more cleanly. It compares the variable against a series of case values and runs the matching one.
let role = 'moderator';switch (role) { case 'guest': console.log('Guest user'); break; case 'moderator': console.log('Moderator user'); break; default: console.log('Unknown user');}
Two parts are essential. The break after each case stops the switch once a match has run, and forgetting it is the classic switch bug, because without break execution “falls through” into the next case and runs it too. The default case is the catch-all that runs when nothing else matched, the equivalent of the final else. If you come from Python, switch is roughly the modern match statement, and JavaScript has had it far longer.
Repeating with the for loop
A loop runs a block of code repeatedly. The for loop is the workhorse when you know how many times to repeat, and it packs three parts into its header.
for (let i = 0; i < 5; i++) { console.log('Hello world');}
Those three parts, separated by semicolons, are the initial expression that sets up a counter, the condition checked before each pass, and the increment that runs after each pass. Read it as “start i at zero, keep going while i is less than five, and add one to i each time,” which runs the body exactly five times. This counter-and-condition structure is so standard that you will recognise it instantly once you have written a few.
The while and do-while loops
When you do not know in advance how many repetitions you need, the while loop is more natural. It simply repeats as long as its condition stays true, and you manage the controlling variable yourself, declaring it before the loop and updating it inside.
let i = 0;while (i <= 5) { if (i % 2 !== 0) console.log(i); // print only odd numbers i++;}
This walks the numbers up to five and uses the modulo operator to print only the odd ones. The close cousin is the do-whileloop, which is identical except that it checks its condition at the end rather than the start, which guarantees the body runs at least once.
let i = 0;do { if (i % 2 !== 0) console.log(i); i++;} while (i <= 5);
The difference matters only in the edge case where the condition is false from the very beginning: a while loop would skip entirely, while a do-while always runs once before checking.
The trap: infinite loops
Both while and do-while come with a serious hazard. If the controlling variable never changes in a way that makes the condition false, the loop runs forever and freezes your program.
let i = 0;while (i < 5) { console.log(i); // i never changes, so this runs forever}
The fix is simply to remember the update, the i++, inside the loop body. The same trap hides in a do-while if you forget to increment. This is the most common loop mistake, so whenever you write a while loop, your first instinct should be to ask “what changes each pass to eventually end this?”
Looping over objects and arrays
JavaScript has two specialised loops for stepping through collections, and keeping them straight matters. The for-in loop iterates over the keys of an object.
const person = { name: 'Andrei', age: 30};for (let key in person) { console.log(key, person[key]);}
Each pass gives you a property name in key, and you reach the value with bracket notation, person[key], exactly the dynamic-key case from the objects article where dot notation cannot help because the key lives in a variable. The for-ofloop, by contrast, iterates over the values of an array.
const colors = ['red', 'green', 'blue'];for (let color of colors) { console.log(color);}
Here color holds each item in turn, with no index juggling at all. The rule of thumb is short: use for-in for the keys of an object, and for-of for the values of an array. Mixing them up is a frequent beginner error, partly because Python’s single forloop blurs the distinction these two keep separate.
Steering a loop with break and continue
Sometimes you want to stop a loop early or skip a single pass, and two keywords do exactly that. break exits the loop immediately.
let i = 0;while (i <= 10) { if (i === 5) break; // stop as soon as we reach 5 console.log(i); i++;}
This prints zero through four and then stops the moment i reaches five, abandoning the rest of the loop entirely. Its companion, continue, does not stop the loop but skips the remainder of the current pass and jumps straight to the next one, which is handy for ignoring items that do not interest you while carrying on through the rest.
Putting it together: processing a list of orders
The clearest way to see control flow cooperate is a small data-processing task, the kind a real program does constantly. Here we loop over a list of orders, skip the cancelled ones, stop if we hit a suspiciously large order that needs manual review, and total up the valid revenue.
const orders = [ { id: 1, amount: 40, status: 'paid' }, { id: 2, amount: 0, status: 'cancelled' }, { id: 3, amount: 75, status: 'paid' }, { id: 4, amount: 5000, status: 'paid' }, { id: 5, amount: 30, status: 'paid' }];let total = 0;for (let order of orders) { if (order.status === 'cancelled') continue; // skip cancelled orders if (order.amount > 1000) break; // stop at one needing review total += order.amount;}console.log(total); // 115
Every piece is at work here. The for-of loop walks the array of order objects, the first if with continue skips the cancelled order without adding anything, and the second if with break halts the whole loop the moment it meets the five-thousand order, so neither that order nor the one after it is counted. The compound assignment adds each surviving amount into the running total, which ends at 115, the sum of the forty and seventy-five paid orders before the loop stopped. Change the data and the behaviour adapts automatically, which is the entire point of control flow: the same code makes different decisions depending on what it meets.
Conclusion
Control flow is what turns a straight-line script into a program that thinks. Use if, else if, and else for decisions, and switchwhen you are matching one variable against many exact values, remembering the break after each case. Reach for a for loop when you know the count, and a while or do-while when you do not, always making sure something changes each pass so the loop can end. Step through an object’s keys with for-in and an array’s values with for-of, and steer any loop from the inside with break to stop and continue to skip. Together these few constructs express essentially every decision and repetition your programs will ever need.
See you soon.
[…] JavaScript Control Flow and Loops […]
[…] Control Flow: https://datalad.co.uk/javascript-control-flow-and-loops/ […]
[…] workbook is the hands-on companion to the Control Flow and Loops article. Read the theory there, then work through the ten use cases below. Each one is a complete, […]
[…] the full background, read the guide to JavaScript control flow and loops. To practise, work through the code-along […]