JavaScript Control Flow
Control flow is the order in which statements are executed in a program. By default, JavaScript runs code from top to bottom. Conditional statements, loops, and error handling change this flow.
Program Execution Order
JavaScript executes statements sequentially by default. Each line runs after the previous one completes. Control flow statements alter this linear execution.
// Code runs top to bottom
let a = 10;
let b = 20;
let sum = a + b;
console.log("Step 1: a = " + a);
console.log("Step 2: b = " + b);
console.log("Step 3: sum = " + sum);
// Output: Step 1: a = 10
// Output: Step 2: b = 20
// Output: Step 3: sum = 30| Control Flow Type | Statements | Effect |
|---|---|---|
| Sequential | (default) | Execute line by line |
| Conditional | if, else, switch | Branch based on condition |
| Loop | for, while, do...while | Repeat a block of code |
| Jump | break, continue, return | Skip to another point |
| Exception | try, catch, finally, throw | Handle errors |
Conditional Branching
Conditional statements create branches in your code. Only one branch executes based on the evaluated condition. This is the most common form of control flow.
let hour = 14;
let greeting;
// The program takes one of three paths
if (hour < 12) {
greeting = "Good morning";
console.log("Took morning branch");
} else if (hour < 18) {
greeting = "Good afternoon";
console.log("Took afternoon branch");
} else {
greeting = "Good evening";
console.log("Took evening branch");
}
console.log(greeting);
// Output: Took afternoon branch
// Output: Good afternoon
// Switch branching
let action = "save";
switch (action) {
case "save":
console.log("Saving...");
break;
case "delete":
console.log("Deleting...");
break;
default:
console.log("Unknown action");
}
// Output: Saving...Loop Flow
Loops change control flow by repeating a block of code. The loop body executes multiple times, with each pass called an iteration. break and continue modify the loop flow.
console.log("Before loop");
for (let i = 0; i < 5; i++) {
if (i === 2) {
console.log(" Skipping " + i);
continue; // Jump to next iteration
}
if (i === 4) {
console.log(" Breaking at " + i);
break; // Exit loop entirely
}
console.log(" Processing " + i);
}
console.log("After loop");
// Before loop
// Processing 0
// Processing 1
// Skipping 2
// Processing 3
// Breaking at 4
// After looptry/catch Flow
Error handling with try/catch changes control flow when exceptions occur. The try block runs normally until an error is thrown, then control jumps to the catch block. The finally block always runs.
function divide(a, b) {
try {
console.log("1. Trying division");
if (b === 0) {
throw new Error("Cannot divide by zero");
}
let result = a / b;
console.log("2. Result: " + result);
return result;
} catch (error) {
console.log("3. Error: " + error.message);
return null;
} finally {
console.log("4. Finally block (always runs)");
}
}
console.log("--- Success case ---");
divide(10, 2);
// 1. Trying division
// 2. Result: 5
// 4. Finally block (always runs)
console.log("--- Error case ---");
divide(10, 0);
// 1. Trying division
// 3. Error: Cannot divide by zero
// 4. Finally block (always runs)return and throw
The return statement exits a function and optionally provides a value. The throw statement creates a custom error and transfers control to the nearest catch block.
// return exits the function immediately
function findFirst(arr, predicate) {
for (let item of arr) {
if (predicate(item)) {
console.log("Found: " + item);
return item; // Exits function (and loop)
}
}
console.log("Not found");
return undefined;
}
let nums = [1, 3, 5, 8, 9];
let even = findFirst(nums, n => n % 2 === 0);
console.log("Result: " + even);
// Found: 8
// Result: 8
// throw transfers control to catch
function validateAge(age) {
if (typeof age !== "number") {
throw new TypeError("Age must be a number");
}
if (age < 0 || age > 150) {
throw new RangeError("Age must be 0-150");
}
return true;
}
try {
validateAge(-5);
} catch (e) {
console.log(e.constructor.name + ": " + e.message);
}
// RangeError: Age must be 0-150