Conditions and loops
Early return, an object map instead of switch, for...of vs for...in.
Updated
What control flow is
By default, code runs top to bottom, line by line. Control flow = the tools that change this:
- conditions — run a block only if something is true;
- loops — run a block several times;
- jumps —
return,break,continue,throwexit early.
Conditions — types and when to use them
| Tool | When |
|---|---|
if / else |
any decision; branches with several lines |
ternary a ? b : c |
choosing between two values inside an expression (JSX, assignment) |
&& |
"show this only if" (in JSX) |
switch |
many cases for the same value, with different logic |
| object map | many cases that just map one value to another |
if / else and early return
function shipping(total, country) {
if (total <= 0) return 0 // special cases exit first
if (country !== 'US') return 50
if (total >= 200) return 0
return 15
}Early return instead of nested ifs: the code stays "flat", and each case is handled and forgotten.
// ✗ the "arrow" of ifs
if (user) {
if (user.isActive) {
if (user.role === 'admin') { ... }
}
}
// ✓
if (!user || !user.isActive) return
if (user.role !== 'admin') return
...The ternary
const label = count === 1 ? 'message' : 'messages'A ternary inside a ternary (a ? b : c ? d : e) = a sign you need an if or an object map.
switch vs object map
switch (status) {
case 'success': return '✓'
case 'error': return '✗'
default: return '?'
}
// the same thing, shorter:
const icons = { success: '✓', error: '✗' }
const icon = icons[status] ?? '?'switch compares with ===. Without return or break, execution continues into the next case (fall-through) — a classic source of bugs.
Loops — types and differences
| Loop | Iterates over | Can stop with break |
When |
|---|---|---|---|
for (const x of arr) |
the values of an iterable (array, string, Map, Set) | yes | walking through a collection |
for (const key in obj) |
the keys of an object | yes | rarely — prefer Object.entries |
for (let i = 0; i < n; i++) |
indexes | yes | you need the index, a step, or to iterate backwards |
while (cond) |
as long as the condition is true | yes | you don't know the number of iterations upfront |
arr.forEach(fn) |
the values | no | simple side effects, no stopping |
map / filter / reduce |
the values, creates a new result | no | transformations — see Arrays |
for (const [key, value] of Object.entries(user)) {
console.log(key, value)
}
for (let i = items.length - 1; i >= 0; i--) { ... } // backwards
let attempts = 0
while (!connected && attempts < 3) { attempts++ }for...in on arrays is a trap: it iterates over string keys ('0', '1') and can include inherited properties.
break and continue
break— exits the loop completely.continue— skips the rest of the current iteration and moves to the next.
for (const order of orders) {
if (order.cancelled) continue
if (order.total > budget) break
process(order)
}Need to stop at the first result? find, some, every stop on their own.
Summary
if+ early return for decisions; a ternary for two values; an object map instead of a longswitch.for...offor collections, the classicforfor indexes,whilefor conditions.forEachcan't be stopped; array methods are for transformations.