π 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
Programs typically execute code sequentially. However, robust applications must make decisionsβexecuting different logic paths based on application state (e.g., user authentication, input validation, feature flags).
Conditionals facilitate this control flow, running code blocks selectively based on boolean conditions. This is essential for creating interactive, responsive applications.
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.