What is the ternary operator?
Back in the JavaScript Operators chapter from the Foundation unit, we learnt about various kinds of operators in JavaScript. There, we saw three categories of operators: unary (one operand), binary (two operands), and ternary (three operands).
The last category here concerns us in this chapter, i.e. a ternary operator.
In JavaScript, there is one and only one ternary operator, often referred to as the conditional operator after its very purpose.
Likewise, because there is precisely one ternary operator, the terms 'conditional operator' and 'ternary operator' are interchangeable in JavaScript.
? :
, is used to return an expression, conditionally.The syntax of the operator is shown as follows:
condition ? trueOutcome : falseOutcome
condition
represents a condition to evaluate to determine what to return.trueOutcome
is an expression to evaluate and return ifcondition
is truthy.falseOutcome
is an expression to evaluate and return ifcondition
is falsey.
Now a question that pops in the mind at this stage is: What's the need of using the conditional operator when we already have if...else
?
Good question. Turns out that the answer already lies in the nature of both these language constructs.
That is, if
and else
are both statements in JavaScript and, therefore, could NOT be embedded into expressions. In contrast, the conditional operator (?:
) is an operator and likewise an expression, and can therefore be a part of expressions, and even statements.
So, while both if
/else
and ?:
evaluate code conditionally, the way they do so is quite different. Let's explore this in more depth.
Comparison to if
and else
Suppose we want to log the text 'Even' if a given integer x
is even, or else log the text 'Odd'.
Here's the program implementing this idea, leveraging if
and else
:
var x = 10;
if (x % 2 === 0) {
console.log('Even');
}
else {
console.log('Odd');
}
Executing this yields 'Even' as one can expect:
The code does its job and is simple. What else can we ask for? Or can we?
Well, if we take a closer look at the code, we notice that we need to make a log in both the cases, whether x
is even or odd. So we don't really need to have console.log()
in two places.
One might propose to create a variable instead and log it in the end, but that's also not the solution, for creating a variable leads to the variable assignment occurring twice:
var x = 10;
var text;
if (x % 2 === 0) {
text = 'Even'; // Assignment here
}
else {
text = 'Odd'; // And assignment here
}
console.log(text);
So this goes into the trash.
Coming back to the console.log()
variant above, what's changing is actually the string that console.log()
is asked to log. We either need to log 'Even'
or 'Odd'
, depending on the value of x
.
Why not leverage the conditional operator to yield the correct string?
Let's do so and see the benefit of it:
var x = 10;
console.log((x % 2 === 0) ? 'Even' : 'Odd');
See how drastically short our code has become, bringing in the conditional operator (?:
) in place of the bulky if
and else
.
Let's understand what the conditional expression is doing above:
(x % 2 === 0)
checks whetherx
is even.- If
(x % 2 === 0)
is truthy, the entire expression resolves to'Even'
. - Otherwise, the entire expression resolves to
'Odd'
.
That simple.
Parentheses around the condition
Reviewing the conditional expression above, because the ?:
operator has a low precedence than many operators in JavaScript, we can let go off the parentheses wrapping x % 2 === 0
in the code above.
So instead of this:
(x % 2 === 0) ? 'Even' : 'Odd'
we can simply have this:
x % 2 === 0 ? 'Even' : 'Odd'
Choose whatever feels comfortable to you. If you're better off with using parentheses (()
), in case you want to be sure of the discrete operations in a complex expression, you're absolutely free to use them.
Let's take this example a bit further to appreciate the significance of the conditional operator.
Suppose now, instead of 'Even' and 'Odd', we want to write out a complete sentence, like 'x is even' or 'x is odd'.
Fortunately, using the conditional operator, this just requires us to make two changes: concatenate the text 'x is '
with the conditional expression; and replace 'Even'
with 'even'
and 'Odd'
with 'odd'
. (Obvious, wasn't that?)
Here's the new code:
var x = 10;
console.log('x is ' + (x % 2 === 0 ? 'even' : 'odd'));
For the sake of readability (and even program correctness sometimes), we've explicitly grouped the conditional expression with a pair of parentheses (()
) to have it be treated as a single, separate expression for the +
operator.
Shown below is the output produced:
Amazing, isn't it?
Since ?:
is an operator (and therefore denotes an expression), it could be blended into any valid JavaScript expression. This is exactly what we've done above, blending ?:
with the string concatenatation (+
) operator.
Clearly, we don't get this priveledge when working with if
and else
, or just about any conditional statement.
Chaining the conditional operator
Akin to how if
and else
can be used to create a chain of different conditions to test for and then fall back with the final else
, we can do the same with the conditional operator.
Let's consider an example to help visualize this better.
Say we want to log the category that a person belongs to, given his/her age in a variable age
(assuming that it holds an integer).
Here are the categories:
- Children — 0 to 14 years old
- Youth — 15 - 24 years old
- Adults and seniors — 25 years old and above
We already saw a similar example back in the JavaScript Conditions — if...else
chapter.
With if
and else
, we can bring this program to life as follows:
var age = 12;
if (age <= 14) {
console.log('Children');
}
else if (age < 24) {
console.log('Youth');
}
else {
console.log('Adults and seniors');
}
Nothing difficult as such.
But let's now try doing this same thing albeit using the conditional operator, or better to say, a chain of conditional operators:
var age = 12;
console.log(
(age <= 14) ? 'Children' : (age <= 24) ? 'Youth' : 'Adults and seniors'
);
The conditions and their corresponding outcomes are the same as before; only the structure of the code has changed.
The chain of two ?:
operators here might seem intimidating to digest but it really isn't that hard. Let's dissect it...
To start with, note that the entire code following (age <= 24)
, and including it, is a single ?:
expression, as highlighted below
(age <= 14) ? 'Children' : (age <= 24) ? 'Youth' : 'Adults and seniors'
We can wrap it with ()
to better visualize the distinct expressions above.
(age <= 14) ? 'Children' : ((age <= 24) ? 'Youth' : 'Adults and seniors')
Execution begins with resolving the very first ?:
operation. The condition (age <= 14)
is evaluated, and if it yields true
, 'Children'
is returned, otherwise the expression following :
is returned.
But the expression following :
(of the first ?:
operator) is yet another conditional operation, likewise before returning it, it needs to be resolved itself.
To resolve this second conditional operation (when the condition of the first one fails), first the condition (age <= 24)
is evaluated, and if it turns out to be true
, 'Youth'
is returned, otherwise the expression following (the second) :
is returned.
This expression is 'Adults and seniors'
. To summarize it, it gets returned when neither of the conditions (age <= 14)
and (age <= 24)
are met.
And that's how the chain of two conditional operators works.
Formatting chained conditional operators
In the code above, where we had a chain of two conditional operators, the main conditional expression got quite long, protruding almost away from the edge of the containing snippet.
When chaining conditional operators, it's often desirable to nicely format the entire expression in a way that it becomes clear as to which parts represent conditions and which parts represent outcome expressions.
One way could be to have all three things on separate lines, as follows:
condition1
? outcome1
: condition2
? outcome2
: outcome3
The ?
or :
symbol appears at the start of all but the first line.
Another way could be to have each condition and its truth outcome on the same line, with the last line denoting the final outcome when none of the preceding conditions is met.
Something as follows:
condition1 ? outcome1
: condition2 ? outcome2
: outcome3
This time, only the :
symbol appears at the start of all but the first line.
If you notice, this resembles the way in which a sequence of if
, else if
, and else
statements could be set up, with each condition and its truth outcome on the same line:
if (condition1) outcome1;
else if (condition2) outcome2;
else outcome3;
Coming back to the formatting of a chain of conditional operators, the question that stands is: Which approach to use?
Well, there's really no right or wrong choice here
We might want to use the first approach, with each part on a separate line, when the expression representing a condition is long and complex enough so as to not leave much room for having its truth outcome expression on the same line.
Similarly, we might want to use the second approach to restate the general pattern of setting up if
, else if
, and else
statements, while we have simple expressions for the conditions and the same for the outcomes.