🔀 Lesson 5: Conditionals
Teach your programs to make decisions — run different code depending on whether conditions are true or false.
🎯 Learning Objectives
By the end of this lesson, you will be able to:
- Write
if,else if, andelsestatements to control program flow - Use
switchstatements for multi-branch decisions - Write concise conditions with the ternary operator (
? :) - Nest conditionals and understand when to avoid deep nesting
- Combine comparisons and logical operators in real conditions
- Apply guard clauses for cleaner, more readable code
Estimated Time: 45 minutes
Project: Build a grade calculator that assigns letter grades
📑 In This Lesson
Introduction
So far, your programs run every line of code from top to bottom, every time. But real programs need to make decisions: show a welcome message if the user is logged in, display an error if the password is wrong, apply a discount if the cart total is over $50.
Conditionals let you run different blocks of code depending on whether a condition is true or false. They're the first step toward making your programs truly interactive.
if / else Statements
The if statement is the most fundamental conditional. It evaluates a condition and runs a block of code only when that condition is true.
Basic if
let temperature = 95;
if (temperature > 90) {
console.log("It's really hot outside! Stay hydrated. 🔥");
}
// This runs because 95 > 90 is true
if / else
Add an else block to handle the case when the condition is false.
let age = 16;
if (age >= 18) {
console.log("You can vote!");
} else {
console.log("You're not old enough to vote yet.");
}
// Output: "You're not old enough to vote yet."
Multiple Conditions with Logical Operators
Remember && (AND) and || (OR) from the last lesson? Here's where they shine.
let age = 25;
let hasTicket = true;
if (age >= 18 && hasTicket) {
console.log("Welcome to the concert!");
} else {
console.log("Sorry, you can't enter.");
}
// Using OR
let isWeekend = true;
let isHoliday = false;
if (isWeekend || isHoliday) {
console.log("No work today! 🎉");
} else {
console.log("Time to get to work.");
}
⚠️ Don't Forget the Curly Braces
You can write a single-line if without braces, but don't. It's a common source of bugs. Always use braces — even for one-liners.
// ❌ Avoid — easy to break when adding lines
if (loggedIn) console.log("Welcome");
// ✅ Always use braces
if (loggedIn) {
console.log("Welcome");
}
else if Chains
When you have more than two possible outcomes, chain else if blocks. JavaScript checks each condition in order and runs the first one that's true.
let score = 82;
if (score >= 90) {
console.log("Grade: A");
} else if (score >= 80) {
console.log("Grade: B");
} else if (score >= 70) {
console.log("Grade: C");
} else if (score >= 60) {
console.log("Grade: D");
} else {
console.log("Grade: F");
}
// Output: "Grade: B"
💡 Order Matters!
Conditions are checked top to bottom. Once a condition is true, its block runs and all remaining else-if/else blocks are skipped. That's why you check the highest grade first — a score of 95 would match >= 90, >= 80, and >= 70, but only the first match runs.
Real-World Example: Time-Based Greeting
let hour = new Date().getHours(); // 0–23
if (hour < 12) {
console.log("Good morning! ☀️");
} else if (hour < 17) {
console.log("Good afternoon! 🌤️");
} else if (hour < 21) {
console.log("Good evening! 🌅");
} else {
console.log("Good night! 🌙");
}
switch Statements
When you're comparing one value against many specific options, a switch statement can be cleaner than a long else if chain.
let day = "Wednesday";
switch (day) {
case "Monday":
console.log("Start of the work week 😩");
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
console.log("Midweek grind 💪");
break;
case "Friday":
console.log("TGIF! 🎉");
break;
case "Saturday":
case "Sunday":
console.log("Weekend vibes! 🏖️");
break;
default:
console.log("That's not a valid day.");
}
// Output: "Midweek grind 💪"
How switch Works
- JavaScript evaluates the expression in
switch() - It compares the result to each
caseusing strict equality (===) - When a match is found, that block runs
breakexits the switch — without it, execution "falls through" to the next case!defaultruns if no case matches (likeelse)
❌ Don't Forget break!
Without break, JavaScript falls through to the next case. This is intentional in the Tuesday/Wednesday/Thursday example above (they share the same output), but it's a common bug when unintended.
// ❌ Bug! Missing break causes fall-through
let fruit = "apple";
switch (fruit) {
case "apple":
console.log("Apples are $1.50/lb");
// No break! Falls through to next case!
case "banana":
console.log("Bananas are $0.75/lb");
break;
}
// Output: BOTH lines print!
// "Apples are $1.50/lb"
// "Bananas are $0.75/lb"
When to Use switch vs. if/else
Use switch When |
Use if/else When |
|---|---|
| Comparing one value to many exact matches | Checking ranges or complex conditions |
| Each case is a specific value (string, number) | Conditions use &&, ||, >, <, etc. |
| Multiple cases share the same code | Conditions are unrelated to each other |
The Ternary Operator
The ternary operator (? :) is a compact way to write a simple if/else that produces a value. It's the only JavaScript operator that takes three operands.
// Syntax: condition ? valueIfTrue : valueIfFalse
let age = 20;
let status = age >= 18 ? "adult" : "minor";
console.log(status); // "adult"
// Equivalent if/else:
// let status;
// if (age >= 18) {
// status = "adult";
// } else {
// status = "minor";
// }
Common Use Cases
// Assigning a value based on a condition
let score = 85;
let result = score >= 60 ? "Pass" : "Fail";
console.log(result); // "Pass"
// Inside template literals
let items = 3;
console.log(`You have ${items} item${items === 1 ? "" : "s"} in your cart.`);
// "You have 3 items in your cart."
// Setting a default
let username = "";
let displayName = username ? username : "Guest";
console.log(displayName); // "Guest" (empty string is falsy)
⚠️ Keep Ternaries Simple
Ternaries are great for short, simple conditions. Don't nest them or use them for complex logic — it quickly becomes unreadable.
// ✅ Good — clear and simple
let label = count === 0 ? "empty" : "has items";
// ❌ Bad — nested ternaries are hard to read
let grade = score >= 90 ? "A" : score >= 80 ? "B" : score >= 70 ? "C" : "F";
// Use if/else or else-if for this instead!
Nesting & Guard Clauses
You can nest if statements inside other if statements, but deep nesting makes code hard to follow. Guard clauses are a cleaner alternative.
Nested Conditionals (Often Messy)
// ❌ Deeply nested — hard to follow
function processOrder(user, item) {
if (user) {
if (user.isLoggedIn) {
if (item.inStock) {
if (user.balance >= item.price) {
console.log("Order placed!");
} else {
console.log("Insufficient funds.");
}
} else {
console.log("Item out of stock.");
}
} else {
console.log("Please log in.");
}
} else {
console.log("No user found.");
}
}
Guard Clauses (Much Better)
A guard clause checks for problems early and exits, so the main logic stays flat and readable.
// ✅ Guard clauses — flat and readable
function processOrder(user, item) {
if (!user) {
console.log("No user found.");
return;
}
if (!user.isLoggedIn) {
console.log("Please log in.");
return;
}
if (!item.inStock) {
console.log("Item out of stock.");
return;
}
if (user.balance < item.price) {
console.log("Insufficient funds.");
return;
}
console.log("Order placed!");
}
✅ Pro Tip: Prefer Guard Clauses
Guard clauses handle edge cases and errors first, then let the "happy path" run without nesting. Your code reads like a checklist instead of a maze. This pattern will serve you well as your programs get more complex.
Truthy/Falsy in Conditions
Remember truthy and falsy values from Lesson 4? They work directly in if conditions — you don't need to compare to true or false explicitly.
let username = "Ray";
// ❌ Unnecessary — comparing to truthy/falsy explicitly
if (username !== "" && username !== null && username !== undefined) {
console.log(`Hello, ${username}!`);
}
// ✅ Cleaner — truthy check handles all of the above
if (username) {
console.log(`Hello, ${username}!`);
}
// Works because non-empty strings are truthy
// Empty string, null, and undefined are all falsy
// Common patterns using truthy/falsy
let items = [];
if (items.length) {
console.log(`You have ${items.length} items.`);
} else {
console.log("Your cart is empty.");
}
// 0 is falsy, so empty array's .length (0) goes to else
let errorMessage = "";
if (errorMessage) {
console.log(`Error: ${errorMessage}`);
}
// Empty string is falsy, so this won't run
💡 When to Be Explicit
Truthy/falsy checks are great for strings and objects, but be careful with numbers. If 0 is a valid value (not an error), a truthy check will incorrectly treat it as "missing." In those cases, check explicitly: if (count !== undefined) instead of if (count).
Hands-on Exercise
🏋️ Exercise: Grade Calculator
Objective: Build a program that takes a numeric score and outputs the letter grade, plus a message for each grade level.
Instructions:
// Grade Calculator
// TODO: Set the student's score
// const studentName = "Alex";
// const score = 78;
// TODO: Use if/else if/else to determine the letter grade:
// 90–100: "A"
// 80–89: "B"
// 70–79: "C"
// 60–69: "D"
// Below 60: "F"
// TODO: Use a switch on the letter grade to set a message:
// A → "Excellent work!"
// B → "Great job!"
// C → "Solid effort, keep improving!"
// D → "You passed, but review the material."
// F → "Let's set up a study plan."
// TODO: Use a ternary to determine pass/fail (60+ is passing)
// TODO: Log the results:
// "Alex scored 78 (C) — Solid effort, keep improving!"
// "Status: Pass"
// BONUS: Add an edge case check — if score is below 0
// or above 100, log "Invalid score" and skip everything else
💡 Hint
Start with the bonus edge-case check as a guard clause. Then use else if chains for the grade ranges (check highest first). Store the letter grade in a variable so you can use it in the switch statement.
✅ Solution
const studentName = "Alex";
const score = 78;
// Guard clause for invalid scores
if (score < 0 || score > 100) {
console.log("Invalid score. Must be between 0 and 100.");
} else {
// Determine letter grade
let letterGrade;
if (score >= 90) {
letterGrade = "A";
} else if (score >= 80) {
letterGrade = "B";
} else if (score >= 70) {
letterGrade = "C";
} else if (score >= 60) {
letterGrade = "D";
} else {
letterGrade = "F";
}
// Determine message using switch
let message;
switch (letterGrade) {
case "A":
message = "Excellent work!";
break;
case "B":
message = "Great job!";
break;
case "C":
message = "Solid effort, keep improving!";
break;
case "D":
message = "You passed, but review the material.";
break;
case "F":
message = "Let's set up a study plan.";
break;
}
// Ternary for pass/fail
const status = score >= 60 ? "Pass" : "Fail";
// Output
console.log(`${studentName} scored ${score} (${letterGrade}) — ${message}`);
console.log(`Status: ${status}`);
}
🎯 Quick Quiz
Question 1: What does this code output?
let x = 5;
if (x > 10) {
console.log("A");
} else if (x > 3) {
console.log("B");
} else if (x > 1) {
console.log("C");
} else {
console.log("D");
}
Question 2: What happens if you forget break in a switch case?
Question 3: What does let result = 10 > 5 ? "yes" : "no"; assign to result?
Summary
🎉 Key Takeaways
if / elseruns code based on whether a condition is true or falseelse ifchains let you check multiple conditions in order — first match winsswitchcompares one value against many specific options — don't forgetbreak!- Ternary (
? :) is a compact if/else for simple value assignments - Guard clauses check for edge cases early to avoid deeply nested code
- Truthy/falsy values work directly in conditions — no need for explicit comparisons
📚 Additional Resources
- MDN — if...else
- MDN — switch
- javascript.info — Conditional Branching
- MDN — Conditional (Ternary) Operator
🚀 What's Next?
Now your programs can make decisions, but what about repeating actions? In the next lesson, you'll learn about loops — for, while, and for...of — to process data, count, and repeat tasks efficiently.