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
:
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!");
}
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');
}
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');
}
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.
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.");
}
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 if
s and else
s.
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);
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);
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.
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');
}
}
}
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.
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');
}
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
.