article cover

How Ternaries Can Improve Your JavaScript Conditionals

Reed Bargerviews icon-
javascript
javascript

If-else statements in JavaScript are great for what’s known as flow control, in other words, for establishing what happens in our application based on one condition or another.

If-else statements are very easy to read and understand what is happening

For example, say we are making an e-commerce app where users can add items to a cart. In it, we are authenticating our users.

First, we could check to see if we have an authenticated user, and if so, enable them to add an item to their cart.

Else, if they are not authenticated, we have them do something else entirely, like tell the user to login.

const isAuthenticated = false;
let cartItemCount = 0;
if (isAuthenticated) {
// add item to cart
cartItemCount = 1;
} else {
// tell user to login
console.log("Please log in!");
}

Use ternaries

If a user is authenticated, we will set cartItemCount to 1, otherwise, it remains at 0:

const isAuthenticated = false;
let cartItemCount = 0;
if (isAuthenticated) {
// add item to cart
cartItemCount = 1;
} else {
// tell user to login
// console.log("Please log in!");
cartItemCount = 0;
}

Notice the repetition—we have to repeat ourselves by saying cartItemCount two or more times after we declare it as a variable.

Try to imagine how much repetition we would have if we needed to conditionally set multiple variables.

In programming, a large aim is to avoid needlessly repeating ourselves. If you find yourself having to repeat the same operation many times, over and over, try to look for alternative. There’s usually a better pattern to follow.

Fortunately there is a better way to do this—to conditionally set the value of a variable without repeating ourselves and by using less code. We achieve both of these ends by using an operator called a ternary operator.

The Question Mark (?)

We can simplify our code by replacing the if part along with it’s parentheses () with the value we want to apply the condition to (in this case isAuthenticated), and afterwards, add a ?

const isAuthenticated = false;
// let cartItemCount = 0;
// if (isAuthenticated) {
// // add item to cart
// cartItemCount = 1;
// } else {
// // tell user to login
// // alert("Please log in!");
// cartItemCount = 0;
// }
isAuthenticated ?
// if «condition»

Looking back at our previous code, when isAuthenticated was true, cartItemCount was updated to 1.

Here’s the special thing about ternaries in relation to variables—we don’t have to immediately assign our variables.

We don’t have to say if isAuthenticated is true, set cartItemCount is equal to 1:

isAuthenticated ? cartItemCount = 1 // unnecessary assignment

Instead, we can remove the reference to the variable in this part, called the then part of the conditional, and instead move it to the beginning:

const cartItemCount = isAuthenticated ? 1
// «condition» ? «then»
// if isAuthenticated is true, 1 is put in cartItemCount

Ternaries are expressions, unlike if statements

This is because a ternary is an expression, instead of a statement. By definition, all expressions in JavaScript resolve to a value.

What does this mean?

If our ternary runs, and isAuthenticated is true, the then part is executed and returns the value 1. It resolves to the value 1, and therefore can be immediately put in our cartItemCount variable.

This is a great benefit: ternaries allow us to reference the variable we are conditionally setting just once, when the variable is declared.

The Colon (:)

But what about the else condition, if isAuthenticated is false?

This part of the conditional is put after another special symbol, the colon:

const cartItemCount = isAuthenticated ? 1 :
// «condition» ? «then» : «else»

After the colon is where we jump to if our ternary’s condition resolves to false.

Looking at our if statement from before, in the else part, we were setting cartItemCount to 0.

Since we now know that ternaries returns the value they resolve to, we can just put 0 in our else condition and it will immediately be put in our cartItemCount variable as well:

const cartItemCount = isAuthenticated ? 1 : 0;

Finally, let’s console log cartItemCount and see what we get. But before we do, if isAuthenticated is set to true, what do you think the value of cartItemCount will be?

const isAuthenticated = true;
const cartItemCount = isAuthenticated ? 1 : 0;
console.log(cartItemCount); // 1

We get 1.

isAuthenticated resolves to true in our condition, therefore the then condition runs and 1 is implicitly returned and assigned to cartItemCount.

And if we update isAuthenticated to false:

const isAuthenticated = false;
const cartItemCount = isAuthenticated ? 1 : 0;
console.log(cartItemCount); // 0

We get 0.

isAuthenticated is false in our condition, then the else condition runs and 0 is put in cartItemCount.

Use expressions in ternaries, don’t perform actions

And finally, what if instead of just returning a value, we also wanted to do something like we did before, where we were alerting the user to login?

const isAuthenticated = false;
const cartItemCount = isAuthenticated ? 1 : console.log("Please log in");
console.log(cartItemCount);
// Please log in
// undefined

We see our alert, but what happens to cartItemCount? It now has the value undefined instead of 0, which is wrong.

The reason for this is that functions (which includes console.log), if they do not have a return value, return undefined by default.

Know that ternaries are very helpful in some situations, but they shouldn’t be used all the time for every conditional you have to write

Ternaries help us to conditionally assign a variable without repetition, but if you want to perform multiple actions or do something that doesn’t give us a return value, use a normal if statement like we had before.

A more in-depth example

Let’s take a look at another example, where we want to greet a user based on their age.

Let’s say we are getting their age from an input or a form, and we’re putting the result in a variable called age. For our first user, it’s 20:

const age = 20;

Then we want to create a custom greeting for our users based on their age.

To do that, we’ll use an if statement. We’ll conditionally store the greeting text in a variable called greeting.

For now, we’ll just have one condition. If the age is less than 10, we’ll say “Hey there”. Otherwise, if they are any other age, else, we’ll say “That’s an interesting age”

let greeting;
if (age < 10) {
greeting = "Hey there";
} else {
greeting = "That's an interesting age!";
}

So now take a minute, using the if statement we have here and convert it to a ternary.

Our ternary has three parts. First we’ll begin by adding our conditional, which will resolve to a boolean value, true or false. In our case, we need to see if age is less than 10. If that’s true, we want the value of the greeting to be ‘Hey there’. And if this condition resolves to false, the value should be ‘That’s an interesting age’. And we want to conditionally update the variable greeting:

const age = 20;
// let greeting;
// if (age < 10) {
// greeting = "Hey there";
// } else {
// greeting = "That's an interesting age!";
// }
const greeting = age < 10 ? "Hey there" : "That's an interesting age!";
console.log(greeting); // That's an interesting age!

The benefit here, like in the example we saw before, is that we can use const to declare our greeting variable instead of let.

Given how const and let operate, we can see that this is a big win when it comes to the reliability of our code and why we should rewrite basic conditionals to ternaries when can when conditionally assigning variables.

We know, just from looking at greeting that it cannot be reassigned and therefore it’s value will not change in the future, since it was declared with const. And that’s on top of being able to remove several lines of code.

Using multiple ternaries

As we know with if statements, we can chain on multiple conditions with else-if.

Say for example, if the user’s age was greater than 10, we might have the greeting “What’s up?”, and if the user was older than 18, we could say “Greetings.”

We can add both of those conditionals as else-ifs to our original if statement:

let greeting;
if (age < 10) {
greeting = "Hey there";
} else if (age > 18) {
greeting = "Greetings";
} else if (age > 10) {
greeting = "What's up?";
} else {
greeting = "That's an interesting age!";
}

What if we wanted to write the same conditions for our ternary? In fact we can, and that’s by chaining multiple ternaries together.

This is a bit tricky to setup, so let’s walk through this together.

For another ternary to be chained on, it is usually as the else condition of the previous ternary. So if for example, the age of a user is now 12, the else expression is run of our first ternary, and instead of returning “That’s an interesting age”, we want to include our next condition, and therefore our next ternary.

const age = 12;
const greeting = age < 10 ? "Hey there" : «condition»
// if the age is not 10, hit the «else» part, where the next condition will be put

Is the age (12) less than 10?

If it is, we return the text “Hey there”, otherwise, the else condition of the next ternary runs.

And then we provide our next condition—is the age (12) greater than 18?

const greeting = age < 10 ? "Hey there" : age > 18 ? "Greetings" : «condition»

No, 12 is not greater than 18. So we chain on another condition.

Is 12 greater than 10?

const greeting =
age < 10
? "Hey there"
: age > 18
? "Greetings"
: age > 10
? "What's up?"
: "That's an interesting age";
console.log(greeting); // What's up?

Yes, so the text returned will be “What’s up”, else (if none of the conditions match), we’ll return “That’s an interesting age.”

Don’t chain multiple ternaries together

What do you think? Do you like ternaries better now?

No, this is tricky to reason through and write, even for an experienced JS developer.

This highlights an important aspect about ternaries: though you can chain multiple ternary expressions together, you should avoid doing so.

If you’re thinking this conditional is unreadable as the one who wrote it, its even more unreadable for others. Plus it loses the value of simplicity. For complex conditionals, use if statements.

This reveals an important concept about the nature of coding in JavaScript is that clarity and readability should be your focus when writing code, not how short you can make it. Sometimes think using tools like the ternary will make our code better, but sometimes it requires writing more code to make it more comprehensible.

Summary

Let’s review: the basic syntax of the ternary is as follows:

«condition» ? «then expression» : «else expression»;

These three parts, condition, then, and else are why this is called a ternary. Note that the word ternary means to have three elements.

It works like this:

  • If condition is truthy, evaluate and return thenExpression.

  • Otherwise, evaluate and return elseExpression.

We also saw that it implicitly returns the value that is created from either the then or else expression. That’s what makes it so great for conditionally assigning a value to a variable.

Ternary expressions allow your code to be not just more simple, but also more predictable. They do this because they cut down on the number of variables that are being reassigned.

But note that ternaries shouldn’t be used everywhere, say if you need to do multiple things in a conditional such as return a value and perform an action like a console.log.



course cover
Join The 2020 JS Bootcamp Video Course 🏕️
Code ArtistryWatch Now
Reed Barger
Professional JS developer who loves to write. Here to make you a better developer, faster.