Conditionals

May 18, 2026
#javascript #js #conditionals #control-flow

Conditionals let your code make decisions. Instead of running every line top to bottom, you can branch — execute different code depending on whether something is true or false. This is fundamental to every program you’ll ever write.

if Statements

The simplest conditional: run code only if a condition is true.

const temperature = 35;

if (temperature > 30) {
    console.log("It's hot outside!");
}

if…else

Handle both cases:

const age = 17;

if (age >= 18) {
    console.log("You can vote.");
} else {
    console.log("You're not old enough to vote yet.");
}

if…else if…else

Multiple conditions:

const score = 78;

if (score >= 90) {
    console.log("A");
} else if (score >= 80) {
    console.log("B");
} else if (score >= 70) {
    console.log("C");
} else if (score >= 60) {
    console.log("D");
} else {
    console.log("F");
}
// "C"

Conditions are checked top to bottom. The first one that’s true wins — the rest are skipped.

Comparison Operators

Operator Meaning Example
=== Strict equality 5 === 5 → true
!== Strict inequality 5 !== "5" → true
> Greater than 10 > 5 → true
< Less than 3 < 7 → true
>= Greater than or equal 5 >= 5 → true
<= Less than or equal 4 <= 3 → false

Logical Operators

Combine multiple conditions:

const age = 25;
const hasLicense = true;
const isSuspended = false;

// AND (&&) — both must be true
if (age >= 16 && hasLicense) {
    console.log("You can drive.");
}

// OR (||) — at least one must be true
if (age < 16 || !hasLicense) {
    console.log("You cannot drive.");
}

// NOT (!) — inverts a boolean
if (!isSuspended) {
    console.log("License is active.");
}

// Combining them
if (age >= 16 && hasLicense && !isSuspended) {
    console.log("You're good to go!");
}

Truthy and Falsy Values

In JavaScript, any value can be used as a condition. Values are either “truthy” (treated as true) or “falsy” (treated as false).

Falsy values (there are only 8):

false
0
-0
0n        // BigInt zero
""        // empty string
null
undefined
NaN

Everything else is truthy, including:

"0"       // non-empty string (even "0" and "false")
[]        // empty array
{}        // empty object
42        // any non-zero number

This matters because you’ll often see conditions like:

const username = getUserInput();

if (username) {
    // username is not empty/null/undefined
    console.log(`Welcome, ${username}`);
} else {
    console.log("Please enter a username");
}

The Ternary Operator

A compact way to write simple if/else expressions:

// condition ? valueIfTrue : valueIfFalse

const age = 20;
const status = age >= 18 ? "adult" : "minor";
console.log(status);  // "adult"

// Useful for inline decisions
const greeting = `Good ${new Date().getHours() < 12 ? "morning" : "afternoon"}!`;

// In template strings
const items = 3;
console.log(`You have ${items} item${items === 1 ? "" : "s"}`);
// "You have 3 items"

Don’t nest ternaries — they become unreadable. Use if/else instead:

// Bad — hard to read
const result = a > b ? "greater" : a < b ? "less" : "equal";

// Good — clear
let result;
if (a > b) {
    result = "greater";
} else if (a < b) {
    result = "less";
} else {
    result = "equal";
}

switch Statements

When you’re comparing one value against many possible matches:

const day = new Date().getDay();

switch (day) {
    case 0:
        console.log("Sunday");
        break;
    case 1:
        console.log("Monday");
        break;
    case 2:
        console.log("Tuesday");
        break;
    case 3:
        console.log("Wednesday");
        break;
    case 4:
        console.log("Thursday");
        break;
    case 5:
        console.log("Friday");
        break;
    case 6:
        console.log("Saturday");
        break;
}

Grouping cases

const day = "Saturday";

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

switch vs object lookup

For simple value mapping, an object is often cleaner than a switch:

// Instead of a long switch:
const statusCodes = {
    200: "OK",
    201: "Created",
    400: "Bad Request",
    404: "Not Found",
    500: "Server Error"
};

const message = statusCodes[response.status] || "Unknown";

Nullish Coalescing (??)

Returns the right side only if the left side is null or undefined (not for other falsy values like 0 or ""):

const userAge = 0;

// || treats 0 as falsy — wrong!
const age1 = userAge || 25;   // 25 (not what we want)

// ?? only triggers on null/undefined — correct!
const age2 = userAge ?? 25;   // 0 (preserves the valid zero)

// Practical use: config with optional values
function createServer(options) {
    const port = options.port ?? 3000;
    const host = options.host ?? "localhost";
    console.log(`Server at ${host}:${port}`);
}

createServer({ port: 0 });  // "Server at localhost:0" (port 0 is valid)

Optional Chaining (?.)

Safely access nested properties without checking each level:

const user = {
    name: "Alice",
    address: {
        city: "Portland"
    }
};

// Without optional chaining — verbose
const zip = user.address && user.address.zipCode;

// With optional chaining — clean
const zip2 = user.address?.zipCode;       // undefined (no error)
const phone = user.contact?.phone;         // undefined (no error)
const first = user.friends?.[0];           // undefined (no error)
const result = user.getName?.();           // undefined (no error)

Common Patterns

Guard clauses (early returns)

Instead of deeply nested if/else, return early for invalid cases:

// Nested (hard to read)
function processOrder(order) {
    if (order) {
        if (order.items.length > 0) {
            if (order.payment) {
                // actual logic buried deep
                return submitOrder(order);
            }
        }
    }
    return null;
}

// Guard clauses (much cleaner)
function processOrder(order) {
    if (!order) return null;
    if (order.items.length === 0) return null;
    if (!order.payment) return null;

    return submitOrder(order);
}

Default values with destructuring

function createUser({ name, role = "viewer", active = true } = {}) {
    return { name, role, active };
}

createUser({ name: "Alice" });
// { name: "Alice", role: "viewer", active: true }

Conditional object properties

const includeDebug = process.env.NODE_ENV === "development";

const config = {
    apiUrl: "https://api.example.com",
    timeout: 5000,
    ...(includeDebug && { debug: true, verbose: true })
};

Choosing the Right Conditional

Situation Best Choice
Simple true/false branch if/else
Inline value selection Ternary ? :
Multiple exact value matches switch or object lookup
Default for null/undefined ??
Safe nested property access ?.
Many conditions to check if/else if with guard clauses