As you write more and more sophisticated programs, creating lines of code that have to execute one line after another in a set sequence will no longer be sufficient. That's where program flow comes in.
Program flow is a general term which describes the order in which your lines of code are executed. This means that some lines will only be read once, some multiple times, and others may be skipped completely, depending on the situation.
In this first chapter on program flow, we will look at conditional statements.
If/else statements
The if/else statement is one of the most ubiquitous in programming. Whether reacting to user input, the results of calculations, or simply checking whether someone is logged in or not, you will often find yourself using if/else statements.
IF the user is logged in, take them to their home page
ELSE redirect them to the login page
This is known as a conditional statement, because it checks if certain conditions are met, and reacts accordingly. Let's have a look at which kinds of conditions can be used in these statements.
Using booleans
In JavaScript, when using simple booleans for if
/else
statements, the syntax looks like this:
if (myBoolean) {
// react to myBoolean being true
} else {
// react to myBoolean being false
}
So to check if a user is logged in, you can do the following:
let userLoggedIn = true;
if (userLoggedIn) {
console.log('User logged in!');
} else {
console.log('Intruder alert!');
}
In the above case, you will get 'User logged in!'
printed to the console, as the userLoggedIn
boolean is set to true
. If it were set to false
, you would get 'Intruder alert!'
instead.
Using expressions
Instead of using a simple boolean variable as an if
/else
condition, you can also use comparative expressions, where you compare values with each other:
Comparative expressions allow you to compare two values with the following operators:
<
Less than<=
Less than or equal to==
Equal to>=
Greater than or equal to>
Greater than!=
Not equal to
For example:
const numberOfSeats = 30;
let numberOfGuests = 25;
if (numberOfGuests < numberOfSeats) {
// allow more guests
} else {
// do not allow any more guests
}
You can also chain if
/else
statements to react to multiple potential conditions:
if (numberOfGuests == numberOfSeats) {
// all seats are taken
} else if (numberOfGuests < numberOfSeats) {
// allow more guests
} else {
// do not allow any more guests
}
Chaining statements like this allows you to specify different outcomes for different situations.
Practice using if/else statements!
Head to CodePen Exercise P2CH2a and follow the instructions below to practice using if/else statements.
In this exercise, I have made some slight changes to our Episode class. As opposed to stating whether or not an episode has been watched when instantiating an episode, we now simply state the number of minutes that have been watched by the user, passing it as an argument to the constructor.
There are two empty sets of parentheses in our if/else statement. Complete the conditions so that the class' hasBeenWatched property is correctly assigned. The first episode should show as "Already been watched," while the other two should show "Not yet watched."
Note: if the user has started but not finished an episode, they are not considered to have watched it.
Solutions:
Once you've given it a go, watch me code a solution and see how your approach compares. And here is a new CodePen with a solution to the exercice.
A quick word on equality: ==
vs ===
In JavaScript, not all equalities were born equal:
There are ways of checking if two values are equal in JavaScript: ==
and ===
, also known as loose equality and strict equality.
Loose equality checks value, but not type. Therefore, this returns
true
:5 == '5'
On the other hand, strict equality checks value and type. Therefore:
5 === '5'
returnsfalse
.
Similarly, there are two not-equal operators !=
and !==
with the same distinction.
Multiple conditions
There will be situations in which you wish to check multiple conditions for a single outcome, i.e., in the same if
statement. For these purposes, there are logical operators:
&&
— Logical AND — for checking if two conditions are both true.||
— Logical OR — for checking if at least one condition is true.!
— Logical NOT — for checking if a condition is not true.
let userLoggedIn = true;
let userHasPremiumAccount = true;
let userHasMegaPremiumAccount = false;
userLoggedIn && userHasPremiumAccount; // true
userLoggedIn && userHasMegaPremiumAccount; // false
userLoggedIn || userHasPremiumAccount; // true
userLoggedIn || userHasMegaPremiumAccount; // true
!userLoggedIn; // false
!userHasMegaPremiumAccount; // true
Of course, these operators can be mixed and matched for your specific needs.
Time to try out some of these operators in our episode component!
Practice using logical operators!
Head to CodePen Exercise P2CH2b and follow the instructions below to practice using logical operators.
Let's make another modification to the logic in our Episode
class. Your colleague's component now expects each episode to have the following properties:
title
: a string containing the episode's title;duration
: a number, corresponding to the duration of the episode in minutes;watchedText
: a string containing either 'Not yet watched', 'Watching', or 'Watched' depending on how many minutes have been watched;continueWatching
: a boolean which is true if the user has started watching the episode but has not finished, and false otherwise.
You know what to do!
Using one or more if/else statements, add the required logic to the Episode class constructor.
Can you find a way to make your code shorter or easier to read?
Remember to use the this keyword to add new properties to the class.
Solutions:
Once you've given it a go, watch me code a solution and see how your approach compares. And here is a new CodePen with a solution to the exercice.
IMPORTANT: Variable scoping
In JavaScript, variables created with let
or const
can only be seen or used inside the code block where they are declared.
This phenomenon is known as block scoping. Here is an example:
let userLoggedIn = true;
if (userLoggedIn) {
let welcomeMessage = 'Welcome back!';
} else {
let welcomeMessage = 'Welcome new user!';
}
console.log(welcomeMessage); // throws an error
In this code, you have two code blocks as a result of the if
/ else
statement. They are highlighted in the image below:
In both the orange and pink highlighted blocks, declare a variable with let welcomeMessage
. However, these variables are only available inside the blocks where they are declared. This is why, when you try to log the contents of welcomeMessage
to the console, you get an error: as far as the code outside the blocks (also known as the outer or parent scope) is concerned, there is no welcomeMessage
variable!
So, how would we achieve the desired behavior? How do we pass values out from inside a code block?
In this case, one method would be to declare the variable in the outer scope, and then modify it inside the if
/else
blocks:
let userLoggedIn = true;
let welcomeMessage = ''; // declare the variable here
if (userLoggedIn) {
welcomeMessage = 'Welcome back!'; // modify the outer variable
} else {
welcomeMessage = 'Welcome new user!'; // modify the outer variable
}
console.log(welcomeMessage); // prints 'Welcome back!'
Here, because the variable is declared in the parent scope, it is available everywhere, and can be accessed and modified properly.
Switch statements
What if you want to check the value of a variable against a list of expected values, and react accordingly? For that, you use the switch
statement:
Let's say you have some user objects and want to check which kind of account each user has, and send a custom message:
let firstUser = {
name: 'Will Alexander',
age: 33,
accountLevel: 'normal'
};
let secondUser = {
name: 'Sarah Kate',
age: 21,
accountLevel: 'premium'
};
let thirdUser = {
name: 'Audrey Simon',
age: 27,
accountLevel: 'mega-premium'
};
Here, you can use a switch
statement, which takes the variable you wish to check, and a list of the values to check for as cases:
switch (firstUser.accountLevel) {
case 'normal':
console.log('You have a normal account!');
break;
case 'premium':
console.log('You have a premium account!');
break;
case 'mega-premium':
console.log('You have a mega premium account!');
break;
default:
console.log('Unknown account type!');
}
After the code to execute in each case
, add the break
statement. If you do not do this, JavaScript will keep executing the following cases (known as cascading) until it meets a break
statement or the end of the switch
. As you can see in the example, you can also add a default
case which will only be executed if the variable you are checking does not match any of the listed values.
Let's recap!
Congratulations on finishing this chapter! We covered a lot here:
You learned how
if
/else
statements work.You saw the different kinds of conditions you can use for if/else statements.
You learned how to group together different conditions with logical operators.
You explored variable scoping, and the consequences that has on code structure.
You discovered the
switch
statement for checking against a list of expected values.
In the next chapter, we will look at how to repeat tasks with loops.