C
JavaScript/Basics/Lesson 05

Control Flow — if · for · while · switch

45 min·theory
This chapter
4/5

Control Flow — if · for · while · switch

🎯 After reading this lesson

After finishing this lesson, you will be able to confidently do the following 3 things.

  • ✅ Know when to use if-else · switch · ternary
  • ✅ Understand the critical difference between ?? (nullish) and || (falsy)
  • ✅ Know the await compatibility of for · for-of · for-in · forEach

Keep the learning objectives as a checklist — close the lesson only when you can answer all of them.

if / else / ternary — 3 ways to express a *branch*

The most basic if

javascript
const score = 85;

if (score >= 90) {
    console.log('A');
} else if (score >= 80) {
    console.log('B');     // this is printed
} else {
    console.log('C');
}

Conditions are evaluated as truthy/falsy. 0, '', null, undefined, NaN, false are falsy. Everything else is truthy.

javascript
if (user) { ... }              // when user is not null/undefined
if (items.length) { ... }      // when the array has elements
if (!name) { ... }             // when name is an empty string, null, or undefined

Ternary operator — shorthand for a brief if

javascript
const label = age >= 19 ? 'Adult' : 'Minor';

An if that returns a value. Very common inside React JSX:

jsx
<button>{isLoading ? 'Saving...' : 'Save'}</button>

Triple ternary (a ? b : c ? d : e) hurts readability — avoid it. Use if-else instead.

Optional chaining + Nullish coalescing — shorthand branching

javascript
const city = user?.address?.city ?? 'Unknown';

?. — if the left side is null/undefined, immediately returns undefined (avoids TypeError).
?? — uses the right side only when the left is null/undefined. 0 or '' are used as-is.

javascript
const req = { page: 0 };

const page  = req.page ?? 1;    // ?? : uses 1 only when null/undefined
const page2 = req.page || 1;    // || : uses 1 for any falsy value (0 is falsy too)

console.log(page);    // 0   ← ✅ 0 preserved (intended value)
console.log(page2);   // 1   ← ⚠️ 0 is falsy so it becomes 1 — a trap!

The difference from || is a classic vibe-coding trap. 80% of AI-generated code uses ??.

4 types of loops — for · while · for...of · for...in

Classic for

javascript
for (let i = 0; i < 5; i++) {
    console.log(i);   // 0,1,2,3,4
}

Useful when you need to manipulate the index directly (reverse iteration, skipping).

while / do-while

javascript
let n = 0;
while (n < 3) {
    console.log(n++);
}

do {
    console.log('at least once');
} while (false);

For dynamic conditions (waiting for input, retry loops). For general iteration, for-of is better.

for...of — iterate over values (arrays)

javascript
const arr = [10, 20, 30];
for (const v of arr) {
    console.log(v);   // 10, 20, 30
}

The most commonly used array loop. break and continue are supported (a key difference from forEach).

for...in — iterate over keys (objects)

javascript
const obj = { name: 'A', age: 30 };
for (const key in obj) {
    console.log(key, obj[key]);
}

Note: Using for...in on an array gives string indices and may include inherited properties — use for...of for arrays, for...in for objects (or Object.entries).

break · continue

javascript
for (const item of list) {
    if (item.skip) continue;     // skip to next iteration
    if (item.stop) break;        // exit the loop
    process(item);
}

Difference between forEach and for...of — a classic vibe-coding question

javascript
// forEach
[1,2,3].forEach(v => console.log(v));

// for...of
for (const v of [1,2,3]) console.log(v);
forEachfor...of
break/continue❌ not supported (use return to skip to next)✅ supported
async/await❌ does not work✅ works
readabilitynatural for method chainingimperative

Rule: If you need await or break, use for...of; for simple transformations, use map/filter/reduce (forEach is becoming less common).

switch — the fall-through trap

Basic switch

javascript
const role = 'admin';

switch (role) {
    case 'admin':
        console.log('Administrator');
        break;        // *required* break
    case 'user':
        console.log('User');
        break;
    default:
        console.log('Unauthenticated');
}

The fall-through trap

javascript
switch (day) {
    case 'MON':
        console.log('Monday');
        // forgot break → falls through to the next case
    case 'TUE':
        console.log('Tuesday');
        break;
}

With day === 'MON', both "Monday" and "Tuesday" are printed. Missing break is the #1 cause of bugs.

Intentional fall-through — grouping multiple cases

javascript
switch (day) {
    case 'SAT':
    case 'SUN':
        console.log('Weekend');
        break;
    default:
        console.log('Weekday');
}

Object literal as a replacement — more modern

When if-else or switch chains get long, object mapping is cleaner:

javascript
const roleLabel = {
    admin: 'Administrator',
    user: 'User',
    guest: 'Guest'
};
console.log(roleLabel[role] ?? 'Unauthenticated');

A pattern commonly used in JSX/React component branching.

🤖 Try asking AI like this

  • "Convert this if-else chain into a switch"
  • "Check this switch for possible missing breaks"
  • "Refactor this branch into an object mapping"

Knowing control flow lets you precisely direct AI to transform logic, and catch bugs in AI-generated code.

⚡ Try it yourself — if · for · switch

Run all four core control flow constructs (if, ternary, for-of, switch) at once.
✏️ JS 코드
📟 Console output
▶ Press the Run button
⚠️ Runs in a browser sandbox — only console.log() is supported; alert/fetch are not.
Control Flow — if · for · while · switch - JavaScript