Skip to main content

Command Palette

Search for a command to run...

Control Flow in JavaScript

Published
8 min read

What is Control Flow

When you write code, it runs line by line, top to bottom. That is the default. But most real programs cannot work that way — they need to make decisions. Should this user see the dashboard or the login page? Is this score a pass or a fail? Did the user enter a valid age?

Control flow is how you give your program the ability to make those decisions. Instead of always running every line, you control which lines run and which ones get skipped, based on conditions.

Think of it like everyday decisions. If it is raining, you carry an umbrella. Otherwise, you do not. Your brain is running control flow all the time — you just do not call it that.

In code, that looks like this:

if (isRaining) {
  carryUmbrella();
} else {
  leaveUmbrella();
}

That is the core idea. The rest of this guide is just different ways to express similar decisions.


The if Statement

The if statement is the most basic form of control flow. You give it a condition, and if that condition is true, it runs a block of code. If the condition is false, it skips the block entirely and moves on.

if (condition) {
  // runs only when condition is true
}

Real example — checking if someone is old enough to vote:

const age = 20;

if (age >= 18) {
  console.log("You can vote.");
}

If age is 20, the condition age >= 18 is true, so the message prints. If age were 15, the condition would be false, nothing prints, and the program moves on.

Step by step what happens here:

  1. JavaScript evaluates age >= 18

  2. That gives either true or false

  3. If true, the code inside {} runs

  4. If false, the block is skipped


The if-else Statement

The if statement alone handles "do something if true." But what if you also want to do something when the condition is false? That is where else comes in.

if (condition) {
  // runs when condition is true
} else {
  // runs when condition is false
}

Example:

const marks = 45;

if (marks >= 50) {
  console.log("Pass");
} else {
  console.log("Fail");
}

One of these two paths will always run. There is no in-between. Either the condition is true and you get "Pass", or it is false and you get "Fail".

Step by step:

  1. marks >= 50 evaluates to false (since 45 is less than 50)

  2. The if block is skipped

  3. The else block runs

  4. Output: "Fail"


Flowchart of if-else

        [Start]
           |
    [Check condition]
      /          \
   true          false
    |               |
[if block]     [else block]
    \               /
         [End]

Only one branch runs. Once it is done, both paths meet again and the program continues.


The else if Ladder

Sometimes there are more than two possible outcomes. Marks are not just pass or fail — you might want grades. Age is not just adult or minor — there might be different categories. The else if ladder lets you check multiple conditions in sequence.

if (condition1) {
  // runs if condition1 is true
} else if (condition2) {
  // runs if condition1 is false AND condition2 is true
} else if (condition3) {
  // runs if condition1 and condition2 are false AND condition3 is true
} else {
  // runs if none of the above are true
}

Example — grading a student:

const marks = 72;

if (marks >= 90) {
  console.log("Grade: A");
} else if (marks >= 75) {
  console.log("Grade: B");
} else if (marks >= 60) {
  console.log("Grade: C");
} else if (marks >= 40) {
  console.log("Grade: D");
} else {
  console.log("Grade: F");
}

Output: Grade: C

JavaScript checks each condition from top to bottom. The moment one condition is true, it runs that block and skips everything else. It does not check the remaining conditions.

Step by step for marks = 72:

  1. 72 >= 90 — false, skip

  2. 72 >= 75 — false, skip

  3. 72 >= 60 — true, run this block

  4. Output: "Grade: C"

  5. The remaining else if and else are ignored

This "stop at the first true condition" behavior is important. Once a match is found, the rest of the ladder does not matter.


Gotcha — Order Matters

If you flip the conditions carelessly, you get wrong results:

const marks = 95;

if (marks >= 40) {
  console.log("Grade: D");  // this runs for 95 too — wrong
} else if (marks >= 90) {
  console.log("Grade: A");  // never reached
}

Because 95 >= 40 is true, it stops there and prints "Grade: D" for a student who deserved an A. Always order your conditions from most specific to least specific, or highest to lowest when dealing with ranges.


The switch Statement

The switch statement is designed for a specific situation: when you are checking one variable against multiple exact values.

Instead of writing if x === 1, else if x === 2, else if x === 3... you give switch the variable, and then list out cases for each value you want to handle.

switch (variable) {
  case value1:
    // runs if variable === value1
    break;
  case value2:
    // runs if variable === value2
    break;
  default:
    // runs if no case matches
}

Example — printing the day of the week:

const day = 3;

switch (day) {
  case 1:
    console.log("Monday");
    break;
  case 2:
    console.log("Tuesday");
    break;
  case 3:
    console.log("Wednesday");
    break;
  case 4:
    console.log("Thursday");
    break;
  case 5:
    console.log("Friday");
    break;
  case 6:
    console.log("Saturday");
    break;
  case 7:
    console.log("Sunday");
    break;
  default:
    console.log("Invalid day");
}

Output: Wednesday

JavaScript jumps directly to case 3, runs the code there, hits break, and exits the switch block.


What break Does

break tells JavaScript to stop executing the switch block and move on. Without it, JavaScript keeps running the code in the next case even if that case did not match. This is called fall-through.

const day = 3;

switch (day) {
  case 3:
    console.log("Wednesday");
    // no break here
  case 4:
    console.log("Thursday");
    break;
}

Output:

Wednesday
Thursday

Both lines printed even though day is 3 and not 4. That is fall-through. It is rarely what you want by accident, so always add break unless you have a specific reason not to.


The default Case

default is the fallback. It runs when none of the cases match, similar to the final else in an if-else ladder.

const day = 9;

switch (day) {
  case 1:
    console.log("Monday");
    break;
  default:
    console.log("Invalid day number");
}

Output: Invalid day number

You do not have to put default at the end — it can go anywhere — but at the end is the convention and makes the most sense to read.


Switch-Case Branching Diagram

           [switch(variable)]
                   |
      -----------------------------
      |       |        |          |
   case 1   case 2   case 3   default
      |       |        |          |
   [code]  [code]   [code]     [code]
      |       |        |          |
   [break] [break]  [break]       |
      \       \        \          /
               [Continue program]

Each case is a separate branch. break makes sure only one branch runs.


When to Use switch vs if-else

This comes up a lot and there is no single right answer, but here is a practical way to think about it.

Use if-else when:

  • You are checking ranges (marks >= 60)

  • The conditions involve different variables

  • Your conditions involve complex logic (age > 18 && hasID === true)

  • There are just two or three cases

// ranges — if-else is the right tool
if (temperature > 35) {
  console.log("Too hot");
} else if (temperature > 20) {
  console.log("Comfortable");
} else {
  console.log("Cold");
}

Use switch when:

  • You are checking one variable against many exact values

  • The cases are clean and discrete (day numbers, status codes, menu options)

  • Readability matters and there are many cases to handle

// exact values — switch reads much cleaner here
switch (statusCode) {
  case 200:
    console.log("OK");
    break;
  case 404:
    console.log("Not Found");
    break;
  case 500:
    console.log("Server Error");
    break;
  default:
    console.log("Unknown status");
}

Writing this as a chain of else if statements would work, but it would be harder to read. Switch is just the cleaner choice for that pattern.


Gotcha — switch Uses Strict Equality

Switch compares values using ===, not ==. This means type matters.

const input = "1";  // this is a string

switch (input) {
  case 1:
    console.log("Number one");
    break;
  default:
    console.log("No match");
}

Output: No match

The string "1" does not strictly equal the number 1, so the case is skipped. If you are reading user input, it usually comes as a string. Either parse it first with parseInt() or write your cases as strings.

More from this blog