JavaScript Conditionals

Conditionals let your code make decisions. You check a condition and run different code depending on whether it is true or false.

if, else if, and else

The most basic form. Run a block of code if a condition is true, optionally with fallback blocks.

const score = 72;

if (score >= 90) {
  console.log('A');
} else if (score >= 80) {
  console.log('B');
} else if (score >= 70) {
  console.log('C');
} else {
  console.log('Below C');
}
// C

Comparison operators

Use these to compare values inside conditions. Always use === (strict equality) rather than == (loose equality).

OperatorMeaning
===strictly equal (same value and type)
!==strictly not equal
>greater than
<less than
>=greater than or equal to
<=less than or equal to
const time = 14;

if (time < 12) {
  console.log('Good morning');
} else if (time < 18) {
  console.log('Good afternoon');
} else {
  console.log('Good evening');
}

Logical operators

Combine multiple conditions.

  • && (and): both conditions must be true.
  • || (or): at least one condition must be true.
  • ! (not): flips true to false and vice versa.
const hour = 10;
const isCaffeinated = true;

if (hour > 8 && isCaffeinated) {
  console.log('Ready to work');
}

if (hour < 6 || !isCaffeinated) {
  console.log('Need coffee');
}

Ternary operator

The ternary is a one-line shorthand for a simple if/else. Good for assigning a value based on a condition.

condition ? valueIfTrue : valueIfFalse
const age = 20;
const status = age >= 18 ? 'adult' : 'minor';
console.log(status); // adult

You can also use it inline in a string:

const points = 42;
console.log(`You have ${points} ${points === 1 ? 'point' : 'points'}`);
// You have 42 points

Avoid nesting ternaries. If the logic gets complex, use an if/else block instead.

switch statement

switch compares a single value against multiple cases. It is a cleaner alternative to a long chain of else if checks on the same variable.

const day = 'Monday';

switch (day) {
  case 'Saturday':
  case 'Sunday':
    console.log('Weekend');
    break;
  case 'Monday':
    console.log('Start of the work week');
    break;
  case 'Friday':
    console.log('Almost the weekend');
    break;
  default:
    console.log('Midweek');
}
// Start of the work week

The break keyword exits the switch after a matching case runs. Without it, execution falls through to the next case. The default block runs if no case matches.

Nullish coalescing (??)

The ?? operator returns the right-hand value only when the left side is null or undefined.

const userTheme = null;
const theme = userTheme ?? 'light';
console.log(theme); // light

This is different from ||. The || operator treats 0, '', and false as falsy, so it falls through to the default even when those are valid values.

const port = 0;

console.log(port || 3000);  // 3000 (wrong if 0 is a valid port)
console.log(port ?? 3000);  // 0    (correct: 0 is not null or undefined)

Use ?? when you specifically want to fall back only on null or undefined, not on any falsy value.

Optional chaining (?.)

Optional chaining lets you safely access nested properties without throwing an error if something in the chain is null or undefined.

const user = {
  name: 'Anna',
  address: {
    city: 'Copenhagen',
  },
};

// Without optional chaining: throws if address is undefined
const city = user.address.city;

// With optional chaining: returns undefined if anything in the chain is nullish
const city2 = user?.address?.city;
console.log(city2); // Copenhagen

const zip = user?.address?.zip;
console.log(zip); // undefined (no error)

It also works for method calls:

const name = user.getName?.(); // calls getName() if it exists, otherwise returns undefined

And for arrays:

const firstItem = items?.[0];

Optional chaining is especially useful when working with API responses where some fields may be missing.

Common mistakes

Using == instead of ===: Loose equality does type coercion and produces results that are hard to predict. Always use ===.

console.log(0 == false);  // true  (not what you expect)
console.log(0 === false); // false (correct)

Forgetting break in a switch case: Without break, execution falls through to the next case even if it does not match. This is a common source of bugs.

switch (colour) {
  case 'red':
    console.log('Stop');
    // forgot break, falls through to next case
  case 'green':
    console.log('Go');
    break;
}
// If colour is 'red', prints both 'Stop' and 'Go'