I was reading about chained ternary operators in JavaScript and MDN says that they are right associative. This means that they will be evaluated from right to left.
The ternary operator is right-associative, which means it can be "chained" in the following way, similar to an if … else if … else if … else chain:
However, this is confusing me a lot. Here is some sample code:
var AQI = 340;
var result =
AQI > 300 //if condition
? "Air Quality is BAD" //if first condition satisfies
: AQI > 200 //first else-if condition
? "Air Quality is NORMAL"
: AQI > 100 //second else-if condition
? "Air Quality is GOOD"
: "Air Quality is EXCELLENT"; //if all the conditions fail
If the ternary operator is right associative, it would evaluate this part first:
AQI > 100 //second else-if condition
? "Air Quality is GOOD"
: "Air Quality is EXCELLENT";
Since, AQI is over 340, AQI > 100 would be true and we will get "Air Quality is Good". However, the real output is "Air Quality is Bad".
So, is MDN wrong about right associativity or am I misunderstanding something?
Thanks.
CodePudding user response:
Do not confuse associativity and evaluation order. They are different concepts.
Associativity means how operations are grouped. This does not mean the same thing as evaluation order.
Given your example:
AQI > 300 //if condition
? "Air Quality is BAD" //if first condition satisfies
: AQI > 200 //first else-if condition
? "Air Quality is NORMAL"
: AQI > 100 //second else-if condition
? "Air Quality is GOOD"
: "Air Quality is EXCELLENT";
A left-associative operator would interpret it as:
(((AQI > 300 ?
"Air Quality is BAD"
: AQI ) > 200 ?
"Air Quality is NORMAL"
: AQI) > 100 ?
"Air Quality is GOOD"
: "Air Quality is EXCELLENT")
That is, it checks if AQI
is more than 300
and so it then checks if "Air Quality is BAD"
is more than 200
and if so it then checks if "Air Quality is NORMAL"
is more than 100
etc.. This is of course nonsensical.
Right-associative logic would interpret it as:
(AQI > 300 ?
"Air Quality is BAD"
: (AQI > 200 ?
"Air Quality is NORMAL"
: (AQI > 100 ?
"Air Quality is GOOD"
: "Air Quality is EXCELLENT")))
Notice that unlike the left-associative, it completes the right grouping first. So once the grouping is complete it is then evaluated in the normal left-to right order and checks if AQI
is more than 300
and then checks if AQI
if more than 200
and then checks if AQI
is more than 100
. This makes more sense.
CodePudding user response:
Right associative doesn't mean that they're evaluated from right to left. It just means that they're grouped from right to left. So your expression is equivalent to the following code with parentheses, which show how the ternaries are nested.
var result =
AQI > 300 //if condition
?
"Air Quality is BAD" //if first condition satisfies
:
(AQI > 200 //first else-if condition
?
"Air Quality is NORMAL" :
(AQI > 100 //second else-if condition
?
"Air Quality is GOOD" :
"Air Quality is EXCELLENT" //if all the conditions fail
)
);
Parentheses just force grouping, not order of evaluation. It still evaluates the first condition first, then either its then or else consequence expression.
That's why this is effectively like if/else if/.../else