Docs
Module-04-Control-Flow
4.1 If/Else Statements
Overview
Conditional statements are fundamental building blocks of programming that allow your code to make decisions. The if/else statement executes different code blocks based on whether a condition is true or false.
Table of Contents
- •Basic Syntax
- •The if Statement
- •The else Statement
- •The else if Statement
- •Nested Conditionals
- •Truthy and Falsy Values
- •Comparison Operators in Conditions
- •Logical Operators in Conditions
- •Best Practices
- •Common Patterns
Basic Syntax
if (condition) {
// code to execute if condition is true
}
if (condition) {
// code if true
} else {
// code if false
}
if (condition1) {
// code if condition1 is true
} else if (condition2) {
// code if condition2 is true
} else {
// code if all conditions are false
}
The if Statement
The simplest form of conditional execution.
const age = 18;
if (age >= 18) {
console.log('You are an adult');
}
// With a single statement, braces are optional (but recommended)
if (age >= 18) console.log('You are an adult');
// Multiple statements require braces
if (age >= 18) {
console.log('You are an adult');
console.log('You can vote');
}
How It Works
┌──────────────┐
│ Condition │
└──────┬───────┘
│
┌───────┴───────┐
▼ ▼
[true] [false]
│ │
▼ │
┌────────────┐ │
│ Execute │ │
│ if block │ │
└────────────┘ │
│ │
└───────┬───────┘
▼
Continue...
The else Statement
Provides an alternative when the condition is false.
const temperature = 25;
if (temperature > 30) {
console.log("It's hot outside");
} else {
console.log('The weather is pleasant');
}
// Only one branch will execute
const loggedIn = false;
if (loggedIn) {
console.log('Welcome back!');
} else {
console.log('Please log in');
}
Execution Flow
┌──────────────┐
│ Condition │
└──────┬───────┘
│
┌───────┴───────┐
▼ ▼
[true] [false]
│ │
▼ ▼
┌────────┐ ┌────────┐
│ if │ │ else │
│ block │ │ block │
└────────┘ └────────┘
│ │
└───────┬───────┘
▼
Continue...
The else if Statement
Chain multiple conditions together.
const score = 85;
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"
Key Points
| Aspect | Description |
|---|---|
| Order Matters | Conditions are checked top to bottom |
| First Match Wins | Only the first true condition's block runs |
| else is Optional | You can have only if and else if |
| Mutual Exclusivity | Only one block ever executes |
// Order matters - this is wrong!
const num = 95;
if (num >= 60) {
console.log('Pass'); // This runs first!
} else if (num >= 90) {
console.log('Excellent'); // Never reached for 95
}
// Correct order - most specific first
if (num >= 90) {
console.log('Excellent');
} else if (num >= 60) {
console.log('Pass');
}
Nested Conditionals
Conditionals inside other conditionals.
const age = 25;
const hasLicense = true;
if (age >= 18) {
if (hasLicense) {
console.log('You can drive');
} else {
console.log('You need a license to drive');
}
} else {
console.log("You're too young to drive");
}
Flattening with Logical Operators
Often nested conditionals can be simplified:
// Nested (harder to read)
if (age >= 18) {
if (hasLicense) {
console.log('You can drive');
}
}
// Flattened (easier to read)
if (age >= 18 && hasLicense) {
console.log('You can drive');
}
Deep Nesting Warning
// ❌ Bad: Too deeply nested
if (condition1) {
if (condition2) {
if (condition3) {
if (condition4) {
// Do something
}
}
}
}
// ✅ Better: Use early returns or logical operators
if (!condition1) return;
if (!condition2) return;
if (!condition3) return;
if (!condition4) return;
// Do something
Truthy and Falsy Values
JavaScript conditions don't require actual booleans.
Falsy Values
if (false) {
} // boolean false
if (0) {
} // zero
if (-0) {
} // negative zero
if (0n) {
} // BigInt zero
if ('') {
} // empty string
if (null) {
} // null
if (undefined) {
} // undefined
if (NaN) {
} // NaN
// None of the above will execute
Truthy Values
if (true) {
} // boolean true
if (1) {
} // non-zero number
if (-1) {
} // negative number
if ('hello') {
} // non-empty string
if ('0') {
} // string with zero (truthy!)
if ([]) {
} // empty array (truthy!)
if ({}) {
} // empty object (truthy!)
if (function () {}) {
} // function
// All of the above will execute
Practical Examples
const username = '';
if (username) {
console.log(`Hello, ${username}`);
} else {
console.log('No username provided');
}
// Output: "No username provided"
const items = [];
if (items.length) {
console.log('Processing items...');
} else {
console.log('No items to process');
}
// Output: "No items to process"
Comparison Operators in Conditions
| Operator | Description | Example |
|---|---|---|
== | Equal (type coercion) | 5 == "5" → true |
=== | Strict equal | 5 === "5" → false |
!= | Not equal (type coercion) | 5 != "5" → false |
!== | Strict not equal | 5 !== "5" → true |
> | Greater than | 10 > 5 → true |
< | Less than | 10 < 5 → false |
>= | Greater or equal | 10 >= 10 → true |
<= | Less or equal | 10 <= 5 → false |
const value = 10;
if (value === 10) {
console.log('Exactly 10');
}
if (value >= 5 && value <= 15) {
console.log('Between 5 and 15');
}
// Always prefer === over ==
if ('5' == 5) console.log('Coerced equal'); // Runs
if ('5' === 5) console.log('Strictly equal'); // Doesn't run
Logical Operators in Conditions
AND (&&)
All conditions must be true.
const age = 25;
const hasTicket = true;
const notBanned = true;
if (age >= 18 && hasTicket && notBanned) {
console.log('You may enter');
}
OR (||)
At least one condition must be true.
const isAdmin = false;
const isModerator = true;
if (isAdmin || isModerator) {
console.log('You have special privileges');
}
NOT (!)
Inverts the boolean value.
const isLoggedIn = false;
if (!isLoggedIn) {
console.log('Please log in');
}
// Double negation for boolean conversion
const value = 'hello';
if (!!value) {
console.log('Value exists');
}
Complex Conditions
const user = { role: 'admin', active: true, verified: false };
// Combine operators with parentheses for clarity
if ((user.role === 'admin' || user.role === 'moderator') && user.active) {
console.log('User has management access');
}
// Checking multiple values
const status = 'pending';
if (status === 'pending' || status === 'processing' || status === 'queued') {
console.log('Request in progress');
}
// Better: Use includes for multiple checks
if (['pending', 'processing', 'queued'].includes(status)) {
console.log('Request in progress');
}
Best Practices
1. Always Use Braces
// ❌ Bad: Can lead to bugs
if (condition) doSomething();
doSomethingElse(); // This ALWAYS runs!
// ✅ Good: Always use braces
if (condition) {
doSomething();
doSomethingElse();
}
2. Use Strict Equality
// ❌ Bad: Type coercion can cause bugs
if (value == null) {
}
// ✅ Good: Be explicit
if (value === null || value === undefined) {
}
// Or even better:
if (value == null) {
} // This is the ONE exception - checks null/undefined
3. Avoid Negative Conditions When Possible
// ❌ Harder to read
if (!isNotValid) {
// do something
}
// ✅ Easier to read
if (isValid) {
// do something
}
4. Use Early Returns
// ❌ Deep nesting
function process(user) {
if (user) {
if (user.isActive) {
if (user.hasPermission) {
// actual logic here
}
}
}
}
// ✅ Guard clauses
function process(user) {
if (!user) return;
if (!user.isActive) return;
if (!user.hasPermission) return;
// actual logic here
}
5. Keep Conditions Simple
// ❌ Complex inline condition
if (
user.age >= 18 &&
user.country === 'US' &&
user.hasLicense &&
!user.isSuspended &&
user.accountType !== 'trial'
) {
// ...
}
// ✅ Extract to meaningful variable
const canDrive =
user.age >= 18 &&
user.country === 'US' &&
user.hasLicense &&
!user.isSuspended &&
user.accountType !== 'trial';
if (canDrive) {
// ...
}
// ✅ Or use a function
function canUserDrive(user) {
if (user.age < 18) return false;
if (user.country !== 'US') return false;
if (!user.hasLicense) return false;
if (user.isSuspended) return false;
if (user.accountType === 'trial') return false;
return true;
}
if (canUserDrive(user)) {
// ...
}
Common Patterns
Null/Undefined Checking
// Check if variable exists
if (variable !== null && variable !== undefined) {
// use variable
}
// Shorter (checks both null and undefined)
if (variable != null) {
// use variable
}
// Using optional chaining (modern)
if (user?.address?.city) {
console.log(user.address.city);
}
Default Values
// Traditional way
let name;
if (userName) {
name = userName;
} else {
name = 'Guest';
}
// Modern way with ||
const name = userName || 'Guest';
// With ?? for null/undefined only
const name = userName ?? 'Guest';
Toggle Pattern
let isVisible = false;
function toggle() {
if (isVisible) {
isVisible = false;
} else {
isVisible = true;
}
}
// Simpler
function toggle() {
isVisible = !isVisible;
}
Range Checking
const value = 50;
// Check if in range
if (value >= 0 && value <= 100) {
console.log('Value is in valid range');
}
// Helper function
function inRange(value, min, max) {
return value >= min && value <= max;
}
if (inRange(value, 0, 100)) {
console.log('Value is in valid range');
}
Summary
| Statement | Use Case |
|---|---|
if | Execute code when condition is true |
else | Execute code when condition is false |
else if | Check additional conditions |
| Nested | Handle complex multi-level logic |
Key Points
- •Conditions are evaluated as truthy/falsy
- •Only one branch executes in an if/else if/else chain
- •Order matters in else if chains
- •Use
===for strict equality - •Keep conditions simple and readable
- •Use early returns to reduce nesting
Next Steps
- •Practice with the examples in
examples.js - •Complete the exercises in
exercises.js - •Learn about
switchstatements for multiple conditions - •Explore the ternary operator for simple conditionals