Home > OS >  Right Associativity of Chained Ternary Operator in JavaScript
Right Associativity of Chained Ternary Operator in JavaScript

Time:11-24

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

  • Related