Skip to main content
๐Ÿงฑbeginner

Control Flow

if/else, switch, and ternary โ€” the tools that let your code make decisions.

if / else if / else

The most fundamental control structure. Execute different code based on conditions:

hljs javascript
const score = 75;

if (score >= 90) {
  console.log("A โ€” Excellent!");
} else if (score >= 80) {
  console.log("B โ€” Good");
} else if (score >= 70) {
  console.log("C โ€” Average");
} else if (score >= 60) {
  console.log("D โ€” Below average");
} else {
  console.log("F โ€” Needs improvement");
}
// Output: "C โ€” Average"

The conditions are evaluated top to bottom. Once one matches, the rest are skipped.

Truthy and Falsy

JavaScript coerces the condition in if to a boolean. Understanding truthy/falsy values is essential:

hljs javascript
// Falsy values โ€” evaluate as false in conditions:
if (!false)     console.log("false is falsy");
if (!0)         console.log("0 is falsy");
if (!-0)        console.log("-0 is falsy");
if (!0n)        console.log("0n is falsy");
if (!"")        console.log("empty string is falsy");
if (!null)      console.log("null is falsy");
if (!undefined) console.log("undefined is falsy");
if (!NaN)       console.log("NaN is falsy");

// Everything else is truthy, including:
if ("0")  console.log('"0" is truthy!');
if ([])   console.log("[] is truthy!");
if ({})   console.log("{} is truthy!");

โœ…Tip

A quick way to check if a value is truthy: Boolean(value) or !!value.

switch Statement

switch is cleaner than many if/else chains when comparing a single value against multiple options:

hljs javascript
const day = "Monday";

switch (day) {
  case "Monday":
  case "Tuesday":
  case "Wednesday":
  case "Thursday":
  case "Friday":
    console.log("Weekday");
    break;
  case "Saturday":
  case "Sunday":
    console.log("Weekend!");
    break;
  default:
    console.log("Unknown day");
}

โš ๏ธDon't forget break!

Without break, execution falls through to the next case. This is rarely what you want and is a common bug. The example above uses multiple cases intentionally (grouping weekdays), but you almost always need break at the end of each case block.

hljs javascript
// Fall-through bug example:
const grade = "A";
switch (grade) {
  case "A":
    console.log("Excellent");
    // missing break!
  case "B":
    console.log("Good");
    break;
  case "C":
    console.log("Average");
    break;
}
// Output: "Excellent" then "Good" โ€” oops!

Ternary Operator

Perfect for simple two-branch conditions in a single expression:

hljs javascript
const age = 20;
const message = age >= 18 ? "You can vote" : "Too young to vote";
console.log(message); // "You can vote"

// Great for inline JSX/template values
const buttonLabel = isLoading ? "Loading..." : "Submit";
const cssClass = isActive ? "active" : "inactive";

Avoid nesting ternaries โ€” they become unreadable fast:

hljs javascript
// โœ— Hard to read
const result = a > b ? (a > c ? a : c) : (b > c ? b : c);

// โœ“ Use if-else instead
let max;
if (a >= b && a >= c) max = a;
else if (b >= c) max = b;
else max = c;

Short-circuit as Conditionals

&& is often used as a concise conditional:

hljs javascript
const user = { name: "Alice", isAdmin: true };

// Only call the function if isAdmin is true
user.isAdmin && showAdminPanel();

// React equivalent (render a component conditionally)
// {user.isAdmin && <AdminPanel />}

Logical Assignment Operators (ES2021)

These combine logical operators with assignment:

hljs javascript
let a = null;
let b = 0;
let c = "hello";

// Logical OR assignment โ€” assign if left side is falsy
a ||= "default";  // a = "default" (null is falsy)
b ||= 42;         // b = 42 (0 is falsy)
c ||= "other";    // c = "hello" (already truthy)
console.log(a, b, c); // "default", 42, "hello"

// Logical AND assignment โ€” assign if left side is truthy
let x = 10;
let y = 0;
x &&= 99;  // x = 99 (10 is truthy)
y &&= 99;  // y = 0 (0 is falsy, no assignment)
console.log(x, y); // 99, 0

// Nullish assignment โ€” assign only if null/undefined
let config = { timeout: 0 };
config.timeout ??= 3000;  // 0 is not null/undefined, stays 0
config.retries ??= 3;     // undefined, gets set to 3
console.log(config); // { timeout: 0, retries: 3 }

Early Returns

A clean pattern: handle edge cases first and return early, rather than nesting:

hljs javascript
// โœ— Deeply nested
function processUser(user) {
  if (user) {
    if (user.isActive) {
      if (user.hasPermission) {
        return doWork(user);
      } else {
        return "No permission";
      }
    } else {
      return "Inactive user";
    }
  } else {
    return "No user";
  }
}

// โœ“ Early returns โ€” much cleaner
function processUser(user) {
  if (!user) return "No user";
  if (!user.isActive) return "Inactive user";
  if (!user.hasPermission) return "No permission";
  return doWork(user);
}
โ–ถTry it yourself

Key Takeaways

  • if/else if/else for multi-branch decisions
  • switch is cleaner for single-value comparisons โ€” don't forget break
  • Ternary for simple two-choice inline expressions
  • Use early returns to reduce nesting
  • && can act as a conditional in expressions

Ready to test your knowledge?

Take a quiz on what you just learned.

Take the Quiz โ†’