Skip to main content

Module 3: Control Flow & Conditional Statements

This module teaches you how to make decisions in your code using conditional statements and how to control the flow of execution.


1. Conditional Statements​

1.1 if Statement​

const age = 18;

if (age >= 18) {
console.log('You are an adult');
}

1.2 if-else Statement​

const age = 16;

if (age >= 18) {
console.log('You are an adult');
} else {
console.log('You are a minor');
}

1.3 if-else if-else Statement​

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

1.4 Nested if Statements​

const age = 25;
const hasLicense = true;

if (age >= 18) {
if (hasLicense) {
console.log('You can drive');
} else {
console.log('You need a license');
}
} else {
console.log('You are too young to drive');
}
Keep It Simple

Avoid deep nesting. Consider refactoring into separate functions or using early returns.


2. Ternary Operator​

// Syntax: condition ? valueIfTrue : valueIfFalse
const age = 20;
const status = age >= 18 ? 'Adult' : 'Minor';

// Multiple ternaries
const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'F';

// With function calls
const message = isLoggedIn ? getUserData() : showLogin();
Readability

Nested ternaries can be hard to read. Use if-else for complex conditions.


3. Switch Statement​

const day = 'Monday';

switch (day) {
case 'Monday':
console.log('Start of work week');
break;
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
console.log('Midweek');
break;
case 'Friday':
console.log('Almost weekend!');
break;
case 'Saturday':
case 'Sunday':
console.log('Weekend!');
break;
default:
console.log('Invalid day');
}

Switch with Expressions​

const getStatus = (code) => {
switch (code) {
case 200:
return 'OK';
case 404:
return 'Not Found';
case 500:
return 'Server Error';
default:
return 'Unknown Status';
}
};
When to Use Switch

Use switch when you have multiple discrete values to check against a single variable.


4. Truthy and Falsy Values​

Falsy Values (6 total)​

false       // Boolean false
0 // Number zero
'' // Empty string
null // Null
undefined // Undefined
NaN // Not a Number

// All evaluate to false in conditions
if (0) { /* won't execute */ }
if ('') { /* won't execute */ }

Truthy Values​

// Everything else is truthy
true
1, -1, 100
'hello', '0', 'false'
[] // Empty array
{} // Empty object
function(){}// Function

Practical Usage​

// Default values
const name = userName || 'Guest';

// Validation
if (!email) {
console.log('Email is required');
}

// Guard clauses
function processUser(user) {
if (!user) return;
// Process user
}

5. Logical Operators in Conditions​

5.1 AND (&&)​

const age = 25;
const hasLicense = true;

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

// Short-circuit evaluation
const result = user && user.name; // Returns user.name if user exists

5.2 OR (||)​

const role = 'admin';

if (role === 'admin' || role === 'moderator') {
console.log('Has elevated privileges');
}

// Default values
const port = process.env.PORT || 3000;

5.3 NOT (!)​

const isLoggedOut = !isLoggedIn;

if (!isActive) {
console.log('Account is inactive');
}

5.4 Complex Conditions​

if ((age >= 18 && hasLicense) || hasSpecialPermit) {
console.log('Eligible to drive');
}

// Readability improvement
const isEligibleToDrive = (age >= 18 && hasLicense) || hasSpecialPermit;
if (isEligibleToDrive) {
console.log('Eligible to drive');
}

6. Guard Clauses (Early Returns)​

Bad: Deep Nesting​

function processOrder(order) {
if (order) {
if (order.items.length > 0) {
if (order.total > 0) {
// Process order
return 'Order processed';
} else {
return 'Invalid total';
}
} else {
return 'No items';
}
} else {
return 'No order';
}
}

Good: Guard Clauses​

function processOrder(order) {
if (!order) return 'No order';
if (order.items.length === 0) return 'No items';
if (order.total <= 0) return 'Invalid total';

// Process order
return 'Order processed';
}
Best Practice

Use early returns to handle error cases first, keeping the main logic at the lowest indentation level.


7. Nullish Coalescing (??) vs OR (||)​

// OR operator (||)
const port1 = 0 || 8080; // 8080 (0 is falsy)
const name1 = '' || 'Guest'; // 'Guest' (empty string is falsy)

// Nullish coalescing (??)
const port2 = 0 ?? 8080; // 0 (0 is not nullish)
const name2 = '' ?? 'Guest'; // '' (empty string is not nullish)

// Only null and undefined are nullish
const value1 = null ?? 'default'; // 'default'
const value2 = undefined ?? 'default'; // 'default'
Use Case

Use ?? when you want to provide defaults only for null/undefined, not for all falsy values.


8. Optional Chaining (?.)​

const user = {
name: 'John',
address: {
city: 'New York'
}
};

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

// With optional chaining
const zip = user?.address?.zip; // undefined (no error)

// With arrays
const firstItem = items?.[0];

// With functions
const result = obj.method?.();

9. Pattern Matching Alternatives​

Object Lookup Pattern​

// Instead of switch
const statusMessages = {
200: 'OK',
404: 'Not Found',
500: 'Server Error'
};

const message = statusMessages[code] || 'Unknown';

Function Map Pattern​

const operations = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};

const result = operations[operator]?.(x, y);

10. Best Practices​

10.1 Avoid Magic Numbers​

// Bad
if (status === 1) {
// What does 1 mean?
}

// Good
const STATUS_ACTIVE = 1;
const STATUS_INACTIVE = 0;

if (status === STATUS_ACTIVE) {
// Clear intent
}

10.2 Positive Conditionals​

// Bad
if (!isNotValid) {}

// Good
if (isValid) {}

10.3 Explicit Comparisons​

// Less clear
if (items.length) {}

// More clear
if (items.length > 0) {}

10.4 Use Meaningful Variable Names​

// Bad
if (x > 18 && y) {}

// Good
const isAdult = age > 18;
const hasPermission = user.role === 'admin';
if (isAdult && hasPermission) {}

Summary​

In this module, you learned:

  • ✅ if, if-else, and if-else if statements
  • ✅ Ternary operator for simple conditions
  • ✅ Switch statements for multiple cases
  • ✅ Truthy and falsy values
  • ✅ Logical operators (&&, ||, !)
  • ✅ Guard clauses and early returns
  • ✅ Modern features: ??, ?.
  • ✅ Best practices for readable conditions
Next Steps

In Module 4, you'll learn about Loops and Iteration to repeat code execution efficiently.


Practice Exercises​

  1. Write a function that returns the day of week name from a number (1-7)
  2. Create a grade calculator using if-else if
  3. Implement age verification with nested conditions
  4. Refactor nested if statements into guard clauses
  5. Create a simple calculator using switch statement
  6. Write validation logic using optional chaining
  7. Compare behavior of || vs ?? operators
  8. Build a user permission checker with complex conditions

Additional Resources​