Control Flow in Programming
Control structures are like traffic signals for your code - they determine which path your program takes and how many times it travels that path. They allow your programs to make decisions and repeat actions, making them dynamic and intelligent!
graph TD
A[Program Start] --> B{Condition?}
B -->|True| C[Execute Path A]
B -->|False| D[Execute Path B]
C --> E[Continue]
D --> E
E --> F{Loop?}
F -->|Yes| G[Repeat Actions]
G --> F
F -->|No| H[Program End]
style B fill:#f9f,stroke:#333,stroke-width:2px
style F fill:#9cf,stroke:#333,stroke-width:2px
Conditional Statements
if Statement
// Basic if statement
let age = 18;
if (age >= 18) {
console.log("You are an adult");
}
// if-else statement
if (age >= 18) {
console.log("You are an adult");
} else {
console.log("You are a minor");
}
// if-else if-else chain
let 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");
}
Nested if Statements
let age = 25;
let hasLicense = true;
let hasInsurance = true;
if (age >= 18) {
if (hasLicense) {
if (hasInsurance) {
console.log("You can drive!");
} else {
console.log("You need insurance to drive.");
}
} else {
console.log("You need a license to drive.");
}
} else {
console.log("You must be 18 or older to drive.");
}
// Better approach with logical operators
if (age >= 18 && hasLicense && hasInsurance) {
console.log("You can drive!");
} else if (age < 18) {
console.log("You must be 18 or older to drive.");
} else if (!hasLicense) {
console.log("You need a license to drive.");
} else if (!hasInsurance) {
console.log("You need insurance to drive.");
}
Switch Statement
// Basic switch statement
let day = "Monday";
switch (day) {
case "Monday":
console.log("Start of the work week");
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
console.log("Middle of the work week");
break;
case "Friday":
console.log("End of the work week");
break;
case "Saturday":
case "Sunday":
console.log("Weekend!");
break;
default:
console.log("Invalid day");
}
// Switch with expressions
let score = 85;
switch (true) {
case score >= 90:
console.log("Grade: A");
break;
case score >= 80:
console.log("Grade: B");
break;
case score >= 70:
console.log("Grade: C");
break;
case score >= 60:
console.log("Grade: D");
break;
default:
console.log("Grade: F");
}
Ternary Operator
// Basic ternary operator
let age = 20;
let status = age >= 18 ? "adult" : "minor";
// Nested ternary (use sparingly)
let score = 85;
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" :
score >= 60 ? "D" : "F";
// Multiple actions in ternary
let isLoggedIn = true;
isLoggedIn ? (
console.log("Welcome back!"),
showDashboard()
) : (
console.log("Please log in"),
showLoginForm()
);
Logical Short-Circuiting
// AND (&&) short-circuiting
let user = null;
user && user.getName(); // Won't execute getName if user is null
// OR (||) short-circuiting for default values
let name = user.name || "Guest";
// Nullish coalescing (??) - only for null/undefined
let count = 0;
let displayCount = count ?? 10; // Uses 0, not 10
let missingValue = undefined;
let defaultValue = missingValue ?? 10; // Uses 10
// Optional chaining (?.)
let user = {
address: {
street: "123 Main St"
}
};
console.log(user.address?.street); // "123 Main St"
console.log(user.phone?.number); // undefined (no error)
// Combining operators
let streetName = user.address?.street ?? "No address provided";
Loops
for Loop
// Basic for loop
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// Looping through arrays
let fruits = ["apple", "banana", "orange"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
// Reverse loop
for (let i = fruits.length - 1; i >= 0; i--) {
console.log(fruits[i]);
}
// Multiple variables
for (let i = 0, j = 10; i < 5; i++, j--) {
console.log(i, j);
}
// Nested loops
for (let i = 1; i <= 3; i++) {
for (let j = 1; j <= 3; j++) {
console.log(`${i} x ${j} = ${i * j}`);
}
}
while Loop
// Basic while loop
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// Infinite loop with break
while (true) {
let input = prompt("Enter 'quit' to exit:");
if (input === 'quit') {
break;
}
console.log("You entered: " + input);
}
// while loop for unknown iterations
let password = "";
while (password !== "secret123") {
password = prompt("Enter the password:");
}
console.log("Access granted!");
do...while Loop
// Basic do...while loop
let i = 0;
do {
console.log(i);
i++;
} while (i < 5);
// Executes at least once
let number = 10;
do {
console.log("This runs at least once");
} while (number < 5);
// User input validation
let age;
do {
age = parseInt(prompt("Enter your age (must be positive):"));
} while (isNaN(age) || age <= 0);
console.log("Your age is: " + age);
for...in Loop
// Iterating over object properties
let person = {
name: "John",
age: 30,
city: "New York"
};
for (let key in person) {
console.log(key + ": " + person[key]);
}
// Works with arrays but not recommended
let colors = ["red", "green", "blue"];
for (let index in colors) {
console.log(index + ": " + colors[index]); // Logs indices, not values
}
// Checking hasOwnProperty
for (let key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}
for...of Loop
// Iterating over array values
let fruits = ["apple", "banana", "orange"];
for (let fruit of fruits) {
console.log(fruit);
}
// Iterating over string characters
let text = "Hello";
for (let char of text) {
console.log(char);
}
// With array destructuring
let users = [
["John", 30],
["Jane", 25],
["Bob", 35]
];
for (let [name, age] of users) {
console.log(`${name} is ${age} years old`);
}
// Works with other iterables
let set = new Set([1, 2, 3]);
for (let value of set) {
console.log(value);
}
let map = new Map([["a", 1], ["b", 2]]);
for (let [key, value] of map) {
console.log(key + ": " + value);
}
Loop Control Statements
break Statement
// Breaking out of a loop
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // Exit the loop completely
}
console.log(i); // 0, 1, 2, 3, 4
}
// Breaking from nested loops
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) {
break outer; // Breaks both loops
}
console.log(i, j);
}
}
continue Statement
// Skipping iterations
for (let i = 0; i < 5; i++) {
if (i === 2) {
continue; // Skip this iteration
}
console.log(i); // 0, 1, 3, 4
}
// continue with labels
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) {
continue outer; // Skip to next outer loop iteration
}
console.log(i, j);
}
}
Common Loop Patterns
Searching Arrays
// Finding an element
let numbers = [1, 3, 5, 7, 9];
let searchValue = 5;
let found = false;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] === searchValue) {
found = true;
console.log(`Found ${searchValue} at index ${i}`);
break;
}
}
if (!found) {
console.log(`${searchValue} not found`);
}
Filtering Arrays
// Creating a filtered array
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let evenNumbers = [];
for (let num of numbers) {
if (num % 2 === 0) {
evenNumbers.push(num);
}
}
console.log(evenNumbers); // [2, 4, 6, 8, 10]
Accumulating Values
// Sum of array elements
let numbers = [1, 2, 3, 4, 5];
let sum = 0;
for (let num of numbers) {
sum += num;
}
console.log(sum); // 15
// Finding maximum value
let max = numbers[0];
for (let i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
}
console.log(max); // 5
Practical Examples
Password Validator
function validatePassword(password) {
let hasUpperCase = false;
let hasLowerCase = false;
let hasNumber = false;
let hasSpecialChar = false;
if (password.length < 8) {
return "Password must be at least 8 characters long";
}
for (let char of password) {
if (char >= 'A' && char <= 'Z') {
hasUpperCase = true;
} else if (char >= 'a' && char <= 'z') {
hasLowerCase = true;
} else if (char >= '0' && char <= '9') {
hasNumber = true;
} else if ("!@#$%^&*".includes(char)) {
hasSpecialChar = true;
}
}
if (!hasUpperCase) return "Password must contain an uppercase letter";
if (!hasLowerCase) return "Password must contain a lowercase letter";
if (!hasNumber) return "Password must contain a number";
if (!hasSpecialChar) return "Password must contain a special character";
return "Password is valid";
}
Shopping Cart Calculator
function calculateTotal(cart) {
let subtotal = 0;
let taxRate = 0.08;
let shippingRate = 5.99;
for (let item of cart) {
subtotal += item.price * item.quantity;
}
let tax = subtotal * taxRate;
let shipping = subtotal > 50 ? 0 : shippingRate;
let total = subtotal + tax + shipping;
return {
subtotal: subtotal.toFixed(2),
tax: tax.toFixed(2),
shipping: shipping.toFixed(2),
total: total.toFixed(2)
};
}
let cart = [
{ name: "Book", price: 15.99, quantity: 2 },
{ name: "Pen", price: 1.99, quantity: 5 },
{ name: "Notebook", price: 5.99, quantity: 3 }
];
console.log(calculateTotal(cart));
Advanced Patterns
State Machine
let state = "idle";
let fuel = 100;
while (fuel > 0) {
switch (state) {
case "idle":
console.log("Engine idle...");
state = "accelerating";
break;
case "accelerating":
console.log("Speeding up!");
fuel -= 2;
if (fuel < 50) {
state = "cruising";
}
break;
case "cruising":
console.log("Cruising along...");
fuel -= 1;
if (fuel < 20) {
state = "braking";
}
break;
case "braking":
console.log("Slowing down...");
fuel -= 0.5;
if (fuel < 10) {
state = "idle";
}
break;
}
}
console.log("Out of fuel!");
Menu System
function showMenu() {
let choice;
do {
console.log("\n=== Main Menu ===");
console.log("1. View Profile");
console.log("2. Edit Settings");
console.log("3. Check Messages");
console.log("4. Exit");
choice = prompt("Enter your choice (1-4):");
switch (choice) {
case "1":
console.log("Viewing profile...");
break;
case "2":
console.log("Editing settings...");
break;
case "3":
console.log("Checking messages...");
break;
case "4":
console.log("Goodbye!");
break;
default:
console.log("Invalid choice. Please try again.");
}
} while (choice !== "4");
}
Best Practices
mindmap
root((Control Structures Best Practices))
Conditionals
Use === not ==
Keep conditions simple
Avoid deep nesting
Consider early returns
Loops
Choose right loop type
Avoid infinite loops
Use meaningful names
Consider performance
General
Write readable code
Handle edge cases
Test thoroughly
Avoid side effects
Code Style Tips
// Bad - Deep nesting
if (condition1) {
if (condition2) {
if (condition3) {
// Do something
}
}
}
// Good - Guard clauses
if (!condition1) return;
if (!condition2) return;
if (!condition3) return;
// Do something
// Bad - Complex condition
if (user.age >= 18 && user.hasLicense && user.hasInsurance && !user.suspended) {
// Allow driving
}
// Good - Extract to function
function canDrive(user) {
return user.age >= 18 &&
user.hasLicense &&
user.hasInsurance &&
!user.suspended;
}
if (canDrive(user)) {
// Allow driving
}
Assignment: Control Structures
- Create a grade calculator:
- Accept a numeric score (0-100)
- Return letter grade (A-F)
- Handle invalid input
- Add plus/minus grades (e.g., B+, A-)
- Build a number guessing game:
- Generate random number (1-100)
- Allow user to guess
- Give hints (higher/lower)
- Count number of attempts
- Implement play again feature
- Create a prime number checker:
- Check if a number is prime
- Find all primes up to n
- Optimize for performance
- Handle edge cases
- Implement a menu-driven calculator:
- Basic arithmetic operations
- Memory functions (store/recall)
- Input validation
- Graceful exit
Bonus: Create a text-based adventure game with multiple paths and decisions!