Dataslope logoDataslope

Conditionals and Decisions

How a program chooses what to do next — `if`, `else`, `else if`, `switch`, and how to keep them readable.

So far our programs have run their statements straight through from top to bottom. Every line, every time. The instant a program starts making decisions"if the user is logged in, show their name; otherwise show 'Sign in'" — it starts looking like real software.

That capacity for decision-making is called control flow, and the most fundamental tool for it is the if statement.

The if statement

The basic shape:

if (condition) {
  // statements that run only if condition is truthy
}

The condition is any expression. If its value is truthy, the block runs; otherwise it is skipped entirely.

Code Block
JavaScript ES2023+

Run the program. Then change age to 19 and run again. The console.log("You can vote.") line is skipped or executed depending entirely on the condition.

if/else

To do one thing when a condition is true and a different thing otherwise, add else:

Code Block
JavaScript ES2023+

Visually:

That diamond is a decision point in the flow of the program. Every conditional in your code corresponds to one of these diamonds.

if/else if/else

When there are several mutually exclusive cases:

Code Block
JavaScript ES2023+

The runtime checks each condition top-to-bottom. The first one that is true runs; all the rest are skipped. The final else (no condition) catches everything left over.

Order matters. If you wrote the conditions starting from score >= 60 first, every passing score would be labelled "D" because that condition matches first.

Guard clauses: prefer early returns

A common pattern in modern code is to write guard clauses at the top of a function — handle the "bad" or "trivial" cases first and return early, so the main logic stays at the top level without a giant pyramid of nested ifs.

Compare. Both functions compute the same thing.

Code Block
JavaScript ES2023+

The second version is far easier to read, especially as logic grows. Use guard clauses whenever you can.

Boolean style: don't compare to true

A small but important style point:

// awkward
if (isLoggedIn === true) { ... }

// clear
if (isLoggedIn) { ... }

Booleans are already booleans — you don't need to test whether they equal true. Same for the negation: write if (!isLoggedIn), not if (isLoggedIn === false).

switch

When you are dispatching on the value of a single variable, the switch statement is sometimes a clearer alternative to a long if/else if chain:

Code Block
JavaScript ES2023+

A few things to know about switch:

  • The comparison is strict equality (===), so the type matters: case "1" is not the same as case 1.
  • Without a break (or return), execution falls through to the next case. This is sometimes useful (as above, where several days share one outcome), but it is a common source of bugs.
  • The default clause is optional and acts like else.

Many modern codebases avoid switch and use plain if/else if or a lookup object. Use it if it makes a particular piece of code clearer; otherwise, regular conditionals are fine.

A lookup table: a "no-if" alternative

When all your if/else if arms do the same shape of thing (returning a value), an object lookup is often cleaner than any of the above. Build a small table, look up the answer.

Code Block
JavaScript ES2023+

This pattern scales well. Adding a new role is a one-line edit to the table; no code changes.

Combining conditions

You will often need to test more than one thing at once. That is where the logical operators from the previous chapter come in.

Code Block
JavaScript ES2023+

Three guard clauses, each handling one failure case in turn. This is much easier to read than one big condition like if (age >= 25 && hasLicence && hasCard) { ... } else { ... } because the reason for the rejection is preserved.

Putting it together: a FizzBuzz warm-up

The classic beginner exercise: print the numbers 1 to 30, but replace multiples of 3 with "Fizz", multiples of 5 with "Buzz", and multiples of both with "FizzBuzz".

Code Block
JavaScript ES2023+

The order of the conditions is critical: we test the most specific case (% 15 === 0) first, then the more general cases. If we reversed the order, every multiple of 15 would print "Fizz" and the most specific case would never run.

(We have not formally met for loops yet — that is the next page. For now, just take it on faith that the body runs once for each n from 1 to 30.)

Challenge

Challenge
JavaScript ES2023+
Traffic light response

Write a function action(color) that returns:

  • "stop" if the colour is "red"
  • "slow down" if the colour is "yellow"
  • "go" if the colour is "green"
  • "unknown signal" for anything else (including the empty string)

Use comparisons and conditionals, not a lookup table — practise the syntax.


QuestionSelect one

Why do programmers often prefer "guard clauses" (early returns at the top of a function) over deeply nested if statements?

Guard clauses run faster

Guard clauses use less memory

Guard clauses keep the main logic at the top indent level, making the function easier to read and easier to extend

Guard clauses are the only way to return from a function

On this page