Conditionals
Problem Statement
If you're hungry, you make a sandwich. If the traffic light is green, you press the gas pedal. If your rent is due, then you pay your rent. This breaks down into a lot of conditional choices:
if
hungry➡️ make sandwich.else
➡️ don't make sandwich.
if
light is green➡️ press gas pedal.else
➡️ press brake pedal.
if
it's the first of the month➡️ pay rent.else
➡️ don't pay rent.
Writing code involves the same type of logic — we only want an action to happen if a certain condition is met. In the programming world, this is called control flow because, well, it helps control the flow of an application.
Before we dive into JavaScript's conditional structures, let's go over a few concepts that provide the syntactic underpinnings.
Objectives
Explain what constitutes an expression in JavaScript
Organize code using block statements
Describe the difference between truthy and falsy values
Learn to use conditional statements
Explain What Constitutes an Expression in JavaScript
A JavaScript expression is a unit of code that returns a value. Primitive values are expressions because they resolve to a value:
So are arithmetic and string operations. This code resolves to the number 64
:
And this resolves to the string "Hello, world!"
:
Ditto for comparison and assignment operations. This comparison resolves to the boolean true
:
Variable declarations are NOT expressions...
...but variable assignments ARE, resolving to the assigned value (42
, in this case):
Finally, references to variables are also expressions, resolving to the value contained in the variable:
Organize Code Using Block Statements
A block statement is a pair of curly braces ({ }
) used to group JavaScript statements. It plays a role in conditional statements, loops, and functions.
Block statements return the value of the last evaluated expression inside the curly braces. Remember, the variable declarations are not expressions, so the value of 5 * 5 - 5
is returned.
Note: The statement above implicitly returns 20 (the value returned by 5 * 5 - 5
, when evaluated). Functions, which we will discuss in an upcoming lesson, also contain all of their code inside curly braces, but for functions, we need to explicitly use the word return
to tell JavaScript what we want the output to be (if we want one, at all). Just remember that the implicit return is something unique to block statements like the ones we use for if...else
and loop statements.
Describe the Difference Between Truthy and Falsy Values
Truthiness and falsiness indicate what happens when the value is converted into a boolean. If, upon conversion, the value becomes true
, we say that it's a truthy value. If it becomes false
, we say that it's falsy.
In JavaScript, the following values are falsy:
false
null
undefined
0
NaN
An empty string (
``
,''
,""
)
Every other value is truthy.
To check whether a value is truthy or falsy in our browser's JS console, we can pass it to the global Boolean
object, which converts the value into its boolean equivalent:
NOTE: document.all
is also falsy, but don't worry about it for now. (Or ever, really — it's an imperfect solution for legacy code compatibility.) Ready to put that killer new vocabulary to the test? Here we go!
Learn to Use Conditional Statements
In JavaScript, we use three structures for implementing condition-based control flow: the if...else
statement, switch
statement, and ternary operator.
if
statement
if
statementif
statements are the most common type of conditional, and they're pretty straightforward:
If the condition returns a truthy value, run the code inside the block:
If the condition returns a falsy value, do nothing:
else
else
If we want to run some code when the condition returns a falsy
value, we can use an else
clause:
Nested Conditionals
If we have multiple overlapping conditions, we can employ nested conditional statements. For example, instead of just deciding whether the passed-in age
meets the criteria for isAdult
, let's add in some other hallmarks of burgeoning adulthood (in American society, at least): canWork
, canEnlist
, and canDrink
. 16-year-olds can legally work; 18-year-olds can work, enlist, and are legal adults; and 21-year-olds can work, enlist, are legal adults, and can drink (at the federally set minimum age, although there can be state-to-state exceptions for these laws). Let's use these conditions in a nesting example:
else if
else if
Another way to represent multiple possible conditions is with else if
clauses:
As soon as one of the conditions returns a truthy value, the attached code block runs and the conditional exits. If none of the conditions evaluate to a truthy value, then the else
code block runs (or, in the absence of an else
clause, the conditional simply exits). Note that, unlike the nested if
statements above, at most one code block will run. In the absence of an else
statement, it's possible that none of the if
conditions return a truthy value and no block is run. However, it's impossible for more than one block in a linked if...else if...else
control flow to run.
switch
switch
Running multiple blocks in the same control flow is one of the many talents of the switch
statement. The general structure is as follows:
The JavaScript engine evaluates the expression and then compares the returned value against each of the case
values using strict equality (===
):
Generally, we use a switch
statement if we need a conditional that hinges on a single value but requires a separate handler for each potential case. For example, the switch
statement here doesn't require us to repeat the if (order === _____)
line for each possibility:
If we'd like to write out the same code with an if
conditional, it will look like this:
We can also assign the same set of statements to multiple cases. In the following example, if the age
variable contains any number between 13
and 19
, the isTeenager
variable will be set to true
. If it contains anything other than a number between 13
and 19
, none of our case
s will hit, and it will end up at the default
, which sets isTeenager
to false
:
The default
and break
keywords are both optional in basic switch
statements, but useful. In more complicated statements, they become necessary to ensure the correct flow.
break
break
In the previous example, break
is used to stop the switch
statement from continuing to look at case statements. If instead, we wrote the following:
The switch statement would get to a match at case 15
and continue on through to case 19
, setting isTeenager
to true. It would then get to default
and set isTeenager
to false. You will often see switch statements where break
is used in every case as a way to ensure there is no unexpected behavior from multiple cases executing.
However, sometimes we do want to potentially match multiple cases, and we will need to leave out break
in order to do this. There's a neat little trick we can employ that allows us to use comparisons for case
statements. Let's rewrite the above if...else
chain as a more compact, less repetitious switch
statement:
We specified true
as the value to switch
on. All of our case
s are comparisons, and if the comparison returns true
its statements will be run. Because we did not include any break
statements, once one case statement matches, all subsequent statements will execute.
With age
set to 20
in the above example, the first case
, age >= 21
, returns false
and so the assignment of canDrink
never happens. The engine then proceeds to the next case
, age >= 18
, which returns true
, assigning the value true
to isAdult
and canEnlist
. Since it encounters no break
statement, canWork
is then set to true in the last case statement.
default
default
The default
keyword specifies a set of statements to run after all of the switch
statement's case
s have been checked. The only time the default
statements do not run is if the engine hits a break
in one of the case
statements.
It's typically safer to include break
statements because it helps avoid bugs like this:
The 'happy'
case matches and assigns the string 'Heck yea; be happy!'
to response
. However, since we didn't break
after that assignment, the default
case also runs and reassigns "Sorry, I don't know how to respond to that mood."
to response
. Whoops!
Ternary operator
The ternary operator, the final piece of the conditional puzzle, is a good way to represent an if...else
statement in a single line of code:
If the condition returns a truthy value, run the code in expression1
. If the condition returns a falsy value, run the code in expression2
.
In the above example, we assign isAdult
as true
if the condition returns a truthy value and as false
otherwise. We can simplify that a bit and assign the result of the ternary directly to a variable:
If it helps you visualize what's going on, you can wrap the condition, the expressions, or the entire ternary in parentheses:
Top Tip: Be careful to not overuse the ternary operator. It's fine for slimming down a simple if...else
, but be conscious of how easy your code is to understand for an outsider. Remember, you generally write code once, but it gets read (by yourself and others) far more than once. The ternary is often more difficult to quickly interpret than a regular old if...else
, so make sure the reduction in code is worth any potential reduction in readability.
Code Examples
There are tons of control flow structures in the Flatbook project code base, a project that emulates the basic functionality of Facebook.
if...else
if...else
When a guest tries to log in, check whether the provided email and password match an active account:
Ternary operator
When a user logs in, check whether it's their birthday. If it is, set a celebratory message to appear in a banner; else, set the message to an empty string:
switch
switch
Once the user logs in, set their permissions based on the account type:
Conclusion
It's easy to imagine hundreds of other conditionals that go into the functioning of a large site like Flatbook. Conditional statements make the internet go round, so study up! The more comfortable you are with controlling the flow of your code with conditional statements, the more complex websites you will be able to build.
Resources
MDN
Last updated