Conditionals
if/else, ternary, logical operators as control flow, and switch case
Conditionals branch execution based on whether an expression is truthy or falsy.
if/else is the fundamental branch. The else if chain handles multiple cases.
const score = 72;
if (score >= 90) {
console.log("A");
} else if (score >= 80) {
console.log("B");
} else {
console.log("C or below");
}
// C or belowThe ternary operator condition ? a : b is a compact inline branch - appropriate for simple value selection, not for nesting logic.
const age = 20;
const label = age >= 18 ? "adult" : "minor";
console.log(label); // adult|| (OR) returns the first truthy operand, or the last value if all are falsy. && (AND) returns the first falsy operand, or the last value if all are truthy. ?? (nullish coalescing) returns the right side only when the left is null or undefined, unlike ||, which also treats 0 and "" as missing.
const requestedLimit = 0;
const withOr = requestedLimit || 100; // 100 - wrong! 0 is falsy
const withNull = requestedLimit ?? 100; // 0 - correct
console.log(withOr); // 100
console.log(withNull); // 0switch compares the value against each case using strict equality, meaning both the value and the type must match (===). So "1" does not match 1. Each case ends with a break to stop execution. The default block runs when no case matches.
const status = "active";
switch (status) {
case "pending":
console.log("queued");
break;
case "active":
console.log("running");
break;
case "done":
console.log("finished");
break;
default:
console.log("unknown");
}
// runningWithout a break, execution falls through into the next case and keeps running, even if that case's value does not match. This is a common source of bugs.
const status = "pending";
switch (status) {
case "pending":
console.log("queued");
// no break - falls through to "active"!
case "active":
console.log("running");
break;
case "done":
console.log("finished");
break;
default:
console.log("unknown");
}
// queued
// runningIn production
The || defaulting pattern - const host = config.host || "localhost" - silently swallows legitimate falsy values like 0, "", and false. This bites feature-flag evaluations, counter initializations, and port numbers. Default to ?? for optional config and only reach for || when you genuinely want to treat all falsy inputs as absent.