AlgoInsight

Free lesson · JavaScript Basic to Advance

Conditionals: if, else, ternary

Easy5 min read

What Are Conditionals?

A conditional is code that runs only when a certain condition is true. It's how your programs make decisions. Every interactive feature you've ever used — a login check, a form validation, a "show more" toggle — runs on conditionals underneath.

const age = 25;

if (age >= 18) {
  console.log("Adult");
} else {
  console.log("Minor");
}

The if checks a condition. If the condition is true, the block runs. The else is the fallback — it runs when the condition is false. This pattern is the foundation of every program you'll ever write.

JavaScript gives you three tools for conditionals: if/else, the ternary operator, and switch (covered in the next Topic). Knowing when to use each one is part of writing clean code.

The Basic if Statement

The simplest conditional has just an if. No else. When the condition is false, nothing happens.

const isLoggedIn = true;

if (isLoggedIn) {
  console.log("Welcome back!");
}

This is what you use when you want to do something only under a specific condition, with no fallback behavior. Many real-world checks look like this — show a notification if there are unread messages, log an error if a value is missing, run cleanup if a flag is set.

The condition inside the parentheses can be any expression that JavaScript can evaluate to truthy or falsy. We covered truthy and falsy in Topic 2.4 — to remind you, the six falsy values are false, 0, "", null, undefined, and NaN. Everything else is truthy. That means:

if ("hello") {
  console.log("Strings are truthy");
}

if (42) {
  console.log("Non-zero numbers are truthy");
}

if ([]) {
  console.log("Even empty arrays are truthy");
}

if (0) {
  console.log("This won't print");
}

Conditionals don't require explicit booleans. JavaScript will coerce any value to a boolean inside the if. This is convenient, but it's also the source of the "zero bug" we covered in Topic 2.4 — be careful when a value of 0 is meaningful and shouldn't be treated as "no value."

Interactive animation: What each if actually does once its condition is coerced - and the question you probably meant to ask.

Adding else and else if

When you need a fallback, use else. When you need multiple branches, chain them with else if.

const score = 72;

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");
}

JavaScript checks each condition in order. The first one that evaluates to true wins — its block runs and the rest are skipped. The else at the end catches anything that didn't match any earlier condition.

The order matters. If you wrote if (score >= 60) first, it would catch every score 60 or above, and the 90, 80, 70 conditions would never get a chance to match. When building a chain like this, put the most specific conditions first.

The Ternary Operator

When you need to choose between two values based on a condition, the ternary operator lets you do it in one line:

const age = 25;
const status = age >= 18 ? "Adult" : "Minor";
console.log(status);

The syntax is: condition ? valueIfTrue : valueIfFalse. JavaScript evaluates the condition. If true, the whole expression equals the first value. If false, it equals the second.

The ternary is most useful when you're assigning a value based on a condition, not when you're running code. Compare:

// Verbose version with if/else
const age = 25;
let category;
if (age >= 18) {
  category = "Adult";
} else {
  category = "Minor";
}
console.log(category);

// Compact version with ternary
const ageAgain = 25;
const categoryAgain = ageAgain >= 18 ? "Adult" : "Minor";
console.log(categoryAgain);

Both produce the same result. The ternary is shorter, but only when you're doing simple value selection. Once the logic gets complicated, ternaries become hard to read and you should switch back to if/else.

A real-world example where ternaries shine is in template literals or JSX (React):

const userName = "Olena";
const isLoggedIn = true;

const greeting = `Hello, ${isLoggedIn ? userName : "guest"}!`;
console.log(greeting);

Inserting a quick conditional value into a string would be awkward with if/else. The ternary fits cleanly inline.

Interactive animation: An if beside a ternary - the ternary produces a value, so the variable can be const.

Logical Operators in Conditions

Real conditions are often combinations of multiple checks. JavaScript has three logical operators for combining conditions:

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

if (age >= 18 && hasLicense) {
  console.log("Can drive legally");
}

if (hasCar || age >= 18) {
  console.log("Has access to a car somehow");
}

if (!hasCar) {
  console.log("Needs to take public transit");
}

The && and || operators have a behavior called short-circuit evaluation. They stop evaluating as soon as the result is known. For &&, if the left side is falsy, the right side isn't evaluated at all — the result must be falsy. For ||, if the left side is truthy, the right side isn't evaluated — the result must be truthy.

This matters because it lets you write safe checks:

const user = { name: "Olena" };
// const user = null;  // try this version too

if (user && user.name) {
  console.log(`User name is ${user.name}`);
}

If user is null, the && short-circuits before trying to read user.name, which would throw an error. This pattern — guard against null, then access the property — appears constantly in real JavaScript code.

A Decision Framework

graph TD
    A[I need a conditional] --> B{Am I assigning a value<br/>based on a true/false check?}
    B -->|Yes, simple case| C[Use a ternary]
    B -->|No, I'm running code| D{How many branches?}
    D -->|2-3 branches| E[Use if / else if / else]
    D -->|Many branches checking<br/>the same variable| F[Consider switch<br/>covered in next Topic]

    style C fill:#10b981,color:#fff
    style E fill:#7c3aed,color:#fff
    style F fill:#3b82f6,color:#fff
This diagram shows how to choose the right conditional structure. Start by asking whether you're assigning a value based on a true or false check, or running code based on a condition. If you're assigning a value in a simple case, use a ternary. If you're running code, count the branches. Two or three branches work well with if, else if, and else. Many branches that all check the same variable can be cleaner as a switch statement, which we cover in the next Topic.

Common Pitfalls

Interactive animation: Assignment where a comparison should be - the if does not check the value, it changes it.

Warning: Three traps with conditionals.

Using = instead of ===. if (x = 5) assigns 5 to x and then tests if 5 is truthy (it is). You meant if (x === 5). This is one of the most common JavaScript bugs. Linters catch it; pay attention to linter warnings.

Nesting too deeply. Conditionals inside conditionals inside conditionals get hard to read fast. If you're three levels deep, extract logic into a separate function or restructure with early returns. "Flat" code reads better than "pyramid" code.

Forgetting that empty strings and zero are falsy. A common bug: if (value) skips the block when value is "" or 0, but those might be valid inputs. When you need to handle "exists but is empty" differently from "doesn't exist," check for null/undefined explicitly: if (value !== null && value !== undefined). Modern JavaScript has the nullish coalescing operator (Module 10) to make this shorter.

Interactive animation: Reject early, then work flat - a nested pyramid of ifs rewritten with early returns.

Why This Matters in Interviews

Interview: Conditional logic appears in nearly every coding interview problem. The interviewer isn't testing whether you know if/else exists — they're testing whether you can structure decision logic cleanly.

Two patterns interviewers look for: (1) handling edge cases explicitly at the top of a function, so the main logic flows cleanly afterward; (2) avoiding deeply nested conditionals by using early returns. A function that returns early when conditions aren't met reads more clearly than one with everything wrapped in nested if blocks.

Topic 4.6 — Interview Lens: Control Flow and Iteration Patterns — covers the deeper interview-prep treatment, including the patterns interviewers look for in well-structured solutions.

Try It

Exercise: Rewrite this nested conditional using ternary, early returns, or restructuring — whichever you think makes it cleaner:

function describeAge(age) {
  if (age >= 0) {
    if (age < 13) {
      return "Child";
    } else {
      if (age < 20) {
        return "Teenager";
      } else {
        if (age < 65) {
          return "Adult";
        } else {
          return "Senior";
        }
      }
    }
  } else {
    return "Invalid age";
  }
}

The function works correctly but reads badly. There's a clear "pyramid of doom" pattern here that you can flatten. Try at least two different rewrites and compare them. Which one would you want to read at 2 AM when debugging a problem?

Back to JavaScript Basic to Advance