Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

JavaScript if...else Statements

Chapter 22 13 mins

Learning outcomes:

  1. A quick recap
  2. Nesting if and else statements
  3. The else if statement

Introduction

Amongst the most useful aspects of modern-day programming is that of selection statements, also known as conditional statements. These statements allow us to execute a piece of code only when a particular condition is met.

They belong to the more broader category of control flow statements, since they enable us to tap into the flow of control of a program by deciding what to execute and what not to, and so, in this way, ignoring whole blocks of code.

JavaScript provides us with two families of conditional statements: if...else and switch. In this chapter, we aim to explore the former in more detail.

Let's begin...

A quick recap

All the way back in the JavaScript Control Flow chapter, we learnt about the if and else statements. Let's quickly recap both of them.

Starting with if:

The if statement is used to execute a piece of code when a given condition is met.

The syntax of if is as follows:

if (condition)
   statement;

The condition to test for is an expression and is given inside a pair of parentheses (()) following the if keyword, followed by the statement to execute when the condition is met.

The condition is either a Boolean value itself (i.e true or false) or is coerced to a Boolean automatically by JavaScript before being evaluated. We'll see examples of this shortly below.

The former part of an if statement, i.e. the keyword followed by the condition, is often referred to as the header of if. Similarly, the latter part of the statement, i.e. the statement to execute, is referred to as the body of if.

Although there is no restriction to use a block statement, denoted via a pair of braces ({}), as the body of an if statement, we usually do so to favor readability and to, most importantly, get more than one statement to be executed when the underlying condition gets met.

This gives us the following syntax:

if (condition) {
   statement1;
   statement2;
      ...
   statementN;
}

Alright, it's time for some examples.

Suppose that we'd like to make an alert to the user asking him/her to go out with an umbrella if it is raining outside.

In the code below, the fact that it is raining today is represented by the Boolean variable isRaining, and based on its value, we make an alert to the user:

var isRaining = true;

if (isRaining) {
   alert("Don't forget an umbrella!");
}

Live Example

Try changing the value of isRaining to false and then rerun the code — you shouldn't get any alert this time.

We can use any valid expression as the condition in an if statement. It's quite customary to use Boolean and relational operators in the condition of an if statement.

As an example, in the code below, we log 'Even' if the given number n is even.

var n = 10;

if (n % 2 === 0) {
   console.log('Even');
}
Even

Sometimes for the condition, instead of using expressions that directly return Boolean values, we use expressions that return non-Boolean values. In these cases, JavaScript coerces the values to corresponding Booleans before evaluating the given condition.

For instance, in the code below, to check if the given array is non-empty, we simply use arr.length, instead of something such as arr.length !== 0. This is because if the array is non-empty, then its length property would be a non-zero integer, and we already know from the last chapter that non-zero integers coerce to the Boolean true.

var arr = [1, 10, 50];

if (arr.length) {
   console.log('Array is non-empty');
}
Array is non-empty

Even if we read out this code, it's more readable than if we had used arr.length !== 0. That is, it reads like 'if the array has a length, then do this', where 'has a length' means that the length is non-zero.

Moving on, the else statement has the exact opposite behavior to an if statement.

When an if statement's condition fails, the corresponding else statement gets executed.

Here's the syntax of else:

if (condition) 
   statement;
else
   statement;

The else keyword is followed by the statement to execute when the associated if condition fails.

An else statement can't appear on its own; it has to have a preceding if statement.

This makes perfect sense, since even in English language, we use the word 'else' after we've made a preceding claim. For instance, 'if this happens, then do this, or else do that'.

In the code below, we make another alert if there are no signs of rain today:

var isRaining = false;

if (isRaining) {
   alert("Don't forget an umbrella!");
}
else {
   alert("No need for an umbrella.");
}

Live Example

Simple.

With this, our recap of if and else reaches its end. If conceptsAreStillUnclear(), then consider reviewing this section and the chapter JavaScript Control Flow.

Nesting if and else statements

As we know by this stage, the body of an if statement and an else statement can be any valid statement.

Let's suppose that we stick to our idea of using a block statement to encompass multiple sub-statements. In that case, we can put any number of statements inside the block, including more ifs and elses.

Isn't that so?

Nesting conditional statements, i.e. putting conditional statements inside conditional statements, is very common not just in JavaScript but in almost all high-level programming languages.

Let's consider a quick example.

Suppose we have an integer n that is known to be a number in the range 0 - 100 (both inclusive). Our job is to determine if the number has a fractional part or is an integer (without a fractional part). If it's an integer, we have to further determine whether it's even or odd.

Now just by reading this description, we can immediately realize that we need an if statement to check whether n is a fractional number (or maybe even go the other way and check if n is an integral number). If it is a fractional number, we proceed as desired, or otherwise fall back to the else block.

Inside the else block, we assert that n is an integer and hence we lay out another set of if...else statements to check the parity of the integer, i.e. whether it's even or odd.

In the code below, we accomplish this idea with the help of a function to help us test the whole logic on multiple numbers:

function testNumber(n) {
   // Check if n is a fractional number, i.e. with a
   // fractional part, such as 3.5, 50.001.
   if (Math.floor(n) !== n) {
      console.log('Fractional');
   }

   // At this stage, it's known that n is an integer.
   else {
      if (n % 2 === 0) {
         console.log('Even integer');
      }
      else {
         console.log('Odd integer');
      }
   }
}

testNumber(2);
testNumber(60.0005);
testNumber(99);
Even integer Fractional Odd integer

The expression Math.floor(n) !== n returns true if the floor of n, which is an integer, is not equal to n. This means that n was not an integer in the first place, but was instead a fractional number.

Note that the same task above could've been accomplished by swapping the logic of the outer if and else statements.

That is, previously, the if statement was used to check for a fractional number while the else block was used for handling an integral number. Now, we could use the if to check for an integral number and use the else for handling a fractional number.

In the code below, we demonstrate this idea:

function testNumber(n) {
   // Check if n is an integer, i.e. without a
   // fractional part, such as 3, 50, 100.
   if (Math.floor(n) === n) {
      if (n % 2 === 0) {
         console.log('Even integer');
      }
      else {
         console.log('Odd integer');
      }
   }

   // At this stage, it's known that n is a fractional number.
   else {
      console.log('Fractional');
   }
}

testNumber(2);
testNumber(60.0005);
testNumber(99);
Even integer Fractional Odd integer

The code has surely changed, but the underlying logic is still the same, as evident by the console logs.

The else if statement

If we want to execute a piece of code when a given condition is met, we use if. Similarly, if we want a piece of code to execute when the condition fails, we use else.

So far, so good.

But what if there are more conditions to test for?

For instance, we might want to determine the age category that a person belongs to: children in 0 - 14, youth in 15 - 24, adults in 25 - 64, and seniors in 65 and above.

This grouping of ages has been obtained from Statistics Canada's website.

Technically, this can be achieved by simply nesting each subsequent if statement after the first one in the else block of the previous if.

Consider the code below, where we accomplish this very task, with age representing the age of a random person:

var age = 37;

if (age <= 14) {
   console.log('Children');
}
else {
   if (age <= 24) {
      console.log('Youth');
   }
   else {
      if (age <= 64) {
         console.log('Adults');
      }
      else {
         console.log('Seniors');
      }
   }
}
Adults

Notice how the second condition is nested inside the first else, and how the third condition is nested inside the second else.

Although at first glance, this code might seem complex, but really it isn't.

When the first if fails, we consider another condition in its corresponding else block. When that second if fails as well, we consider yet another condition in its corresponding else block. And so on and so forth.

Now, in this case, we had simply three conditions to test, and even those conditions had simple blocks of code associated with them. However, if the number of conditions increases and their associated bodies become more and more complex, then this naive nesting approach would surely come at the cost of code clarity and readability.

Every subsequent condition requires us to indent the code, taking it further and further to the right. Imagine a scenario with five or maybe six conditions. It'll surely not look so clean.

So what to do?

Well, we could keep on using this idea of nesting if inside an else statement, but without using a block statement in else's body. That is, the statement following else would now become an if directly, instead of a block statement containing an if.

In other words, we get to use a single phrase to denote another condition in a chain of if and else statements, and that is else if.

It's utterly important to realize the fact that else if is NOT a keyword in JavaScript; else if is just an else statement whose body is an if statement.

That's it.

Technically, else if can't even be a keyword as it contains a space in it which goes against identifier naming rules of JavaScript.

In the following snippet, we rewrite the code above using the else if approach:

var age = 37;

if (age <= 14) {
   console.log('Children');
}
else if (age <= 24) {
   console.log('Youth');
}
else if (age <= 64) {
   console.log('Adults');
}
else {
   console.log('Seniors');
}
Adults

See how readable this code is than the previous one. The body of every if statement and that of the last else statement is at the same level of indentation, giving us the impression that altogether all the statements make up a single logical unit of code.

Once again, remember that else if is just an else statement (associated with the preceding if) containing an if in its body.

Based on this fact, the very last else statement in the code above (in line 12) doesn't belong to the very first if statement (in line 3). Instead the else in line 6 belongs to the very first if, while the if in line 9 is tied to the very last else.