Control Flow in JavaScript
Use conditionals, switches, loops, and exceptions to direct execution.
if / else if / else
Conditions use JS truthiness; prefer strict comparisons.
const x = 0
if (x < 0) {
// ...
} else if (x === 0) {
// ...
} else {
// ...
}
Tips:
- Chain comparisons explicitly:
x > 0 && x < 10 - Use early returns to reduce nesting
switch
Match against discrete values; remember break to avoid falling through.
const status = 404
switch (status) {
case 200:
case 201:
console.log('ok'); break
case 404:
console.log('not found'); break
default:
console.log('other')
}
Use switch(true) sparingly for range-like branching; consider if/else instead.
Loops
for / while / do..while
for (let i = 0; i < 3; i++) {}
let n = 3
while (n--) {}
do { /* ... */ } while (false)
for..of (iterables)
Preferred for arrays, strings, maps, sets.
for (const v of [10,20,30]) { /* v */ }
for..in (object keys)
Iterates enumerable keys (including inherited). Use with care; prefer Object.keys.
const o = { a: 1 }
for (const k in o) { if (Object.prototype.hasOwnProperty.call(o, k)) {/* ... */} }
Loop control
break exits a loop; continue skips to next iteration. Labels can break outer loops (rare).
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === j) continue outer
}
}
Ternary and logical ops
Ternary for small conditional expressions.
const label = age >= 18 ? 'adult' : 'minor'
Short-circuit defaults:
const name = input || 'guest' // falsy default
const safe = input ?? 'guest' // nullish coalescing (null/undefined only)
const len = maybe && maybe.length // guard
try / catch / finally
Handle exceptions; catch can omit the error binding in modern JS.
try {
risky()
} catch (e) {
console.error(e)
} finally {
cleanup()
}
Optional chaining
Safely access nested properties.
const city = user?.address?.city ?? 'unknown'
Summary
- Use
if/elsefor general branching;switchfor discrete cases - Prefer
for..offor iterables; usefor..inwith own‑property guard - Apply
??/||and optional chaining for robust control flow