The beauty of the conditional (ternary) operator in JavaScript

Blue-yellow-pink neon composed of glass tubes arranged in a shape resembling a schematic map of railway connections

Discover the key to concise and elegant code in JavaScript - the conditional (ternary) operator. In this article, you will learn how it works, when to use it, and when it’s better to use if…else. We will also discuss its role in the context of functional programming, as well as the controversial issue of nesting.

Table of Contents

  1. Intro
  2. When to Use the Ternary Operator
  3. When the if Statement is a Better Choice
  4. The Mystery of the Name Ternary
  5. The Functional Programmer’s Ally
  6. A Few Words on Nesting Ternary Operators
  7. Conclusion

Intro

The conditional operator in JavaScript, often referred to simply as a ternary operator, is an operator that returns a single value based on a condition. This is the only operator in JavaScript that takes three arguments:

  • The condition expression
  • The expression to return when the condition is true (or truthy)
  • The expression to return when the condition is false (or falsy)

Here’s what its syntax looks like:

condition ? expressionIfTrue : expressionIfFalse;

In this structure, the condition is the expression being evaluated, the expressionIfTrue is the code that runs if the condition is true, and the expressionIfFalse is the code that runs if the condition is false. It’s a simple, yet powerful concept.

Often, people view the conditional, or ternary operator as an alternative to an if…else statement. But there are some notable differences to bear in mind:

  • The ternary operator is an expression, not a statement, and as such, it evaluates to a single value. On the contrary, an if…else is a statement and as such, it doesn’t evaluate to anything and may not return anything.
  • As an expression, the ternary operator should not cause side effects. The if…else statement, naturally, tends to bring side effects.

The ternary operator is elegant and concise, but often misunderstood. So, let’s clear up any confusion and learn more about it.

When to Use the Ternary Operator

Picture this: late in the night, with a second cup of coffee by your side, you’re working on a feature for price discounts on an e-commerce site. The business logic is actually quite simple: customers with more than 100 loyalty points get a 10% discount, for others the price remains the same.

You start to write:

let discountPrice;

if (loyaltyPoints > 100) {
  discountPrice = price * 0.9;
} else {
  discountPrice = price;
}

You lean back and look at your code. It’s correct, but it feels verbose for such a simple condition. Then it clicks. All you need to do is evaluate an expression based on a condition: a perfect opportunity to bring in the ternary operator.

You refactor your code:

let discountPrice = loyaltyPoints > 100 ? price * 0.9 : price;

Not bad, you’ve condensed four lines of code into one, without losing any clarity. In fact, it’s way more readable now.

When the if Statement is a Better Choice

A few days later, you find yourself managing database operations for an application. Depending on user input, you either have to write new information to the database or read existing information, then log the result.

You hastily write:

let result = userInput === "update"
  ? writeToDatabase(record)
  : readFromDatabase(record);

logDatabaseOperation(result)

Pausing, you sense there’s something wrong with this code. The ternary operator elegantly handles the condition, it looks clean, but… it triggers side effects. The calls to readFromDatabase and writeToDatabase change something outside of this expression. This is a job for the if…else statement, so you refactor the code:

let result;

if (userInput === "update") {
  result = writeToDatabase(record);
} else {
  result = readFromDatabase(record);
}

logDatabaseOperation(result)

Much better! The if…else statement handles the condition and allows for the side effects necessary for this operation.

Does this mean that the first version would not work? No, it would work flawlessly! So why is it wrong then? Because this is not how the ternary operator is intended to be used. And clean code is, in large part, about intentions. We want to see the intentions while reading someone else’s code. And the intention of the ternary operator is to evaluate an expression and return a single value, and do nothing else. When I see a ternary operator, I expect there to be no side effects. And if there are some, then well, it’s a code smell.

The Mystery of the Name Ternary

One thing we haven’t discussed yet is the name. You might be wondering, “Why ternary?”

The term ternary has its roots in Latin, where it means composed of three parts. In this case, those three parts are the condition to evaluate, the true branch, and the false branch. In computer science ternary refers to something that takes three operands or three arguments. For instance, a function accepting three arguments is called a ternary function. Similarly, a binary function accepts two arguments, and a unary function takes just one. So, this isn’t just a fancy name, but a practical, literal description of this expression’s structure.

The Functional Programmer’s Ally

Functional programming is all about pure functions, immutable data, and avoiding side effects. And for this reason, the ternary operator fits into the functional programming paradigm like a key into a lock.

Used correctly, the ternary operator returns values based on conditions. You can directly use the returned value, just like you would use a value returned from a function. In this sense, it acts like a pure function that evaluates a condition and returns a value without causing any side effects. This makes it a true ally when writing functional JavaScript.

A Few Words on Nesting Ternary Operators

There’s a bit of a debate in the developer community about nested ternary operators. Try searching something like “nested ternary operator opinion” and you will find a ton of opinions, mostly against nesting. Some argue that nested ternary operators aren’t bad, while some will go as far as to say they are “pure evil” and that no respected developer would ever use them. Undeniably, it’s a polarising topic.

But if you dig deeper, you will also find people who provide good and sensible arguments for using nested conditional operators rather than if statements. Notably, Eric Elliott wrote a very good piece arguing that Nested Ternaries are Great. I certainly recommend reading the whole article, but here are his main points:

In Eric’s view, the preference for nested if statements comes from familiarity bias. He argues that in the case of ternary expressions, it would be more accurate to say they are chained rather than nested. Since ternaries are easy to arrange in a straight line, top to bottom, they are naturally easy to read and reduce the cognitive load. Having a strong background in functional programming, Eric also points out that conditional expressions are generally better than if statements because they evaluate to a single value and don’t produce side effects.

I admit that I strongly agree with Eric. Take for example this code written with nested if statements:

const greetingMessage = (isMorning, isWeekend) => {
  if (isMorning) {
    if (isWeekend ) {
      return "Good morning, enjoy your weekend!";
    } else {
      return "Good morning!";
    }
  } else {
    return "Hello!";
  }
};

And now the equivalent using conditional expressions:

const greetingMessage = (isMorning, isWeekend) => 
  isMorning
    ? (isWeekend ? "Good morning, enjoy your weekend!" : "Good morning!")
    : "Hello!";

We could also refactor it into a chained form:

const greetingMessage = (isMorning, isWeekend) =>
  !isMorning
    ? "Hello!"
    : isWeekend 
      ? "Good morning, enjoy your weekend!" 
      : "Good morning!";

To me, both versions with nested ternary operators look more readable and elegant. But you don’t have to agree with me. As this is a debatable topic, you and your team should reach a consensus and follow common practice.

Conclusion

So there you have it, the conditional (ternary) operator is a powerful tool in JavaScript. When used appropriately, it will make your code cleaner, leaner, and more elegant. But remember to use it judiciously. When your code needs to produce side effects, you should definitely not use a ternary operator and resort to an if statement. As with anything in programming, there is no one-size-fits-all solution. Happy coding, may your code be clean and elegant!

Ikona Smiley Follow Us!
Logo FacebookLogo Twitter

Copyright 2022 – 2023 ©
Michał Wilkosiński CONIFER MEDIA
All rights reserved