Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this comma inside a ternary operator throw a syntax error in JavaScript?

Tags:

I noticed something odd when trying to use the comma operator inside the conditional (ternary) operator for logging. Here's a contrived example:

const a = 2;  const b = 1;  a > b ? console.log(a), a : b; //I expect this to log and evaluate to a

But instead I'm met with this:

Uncaught SyntaxError: Unexpected token , 

According to the MDN documentation, the conditional operator accepts two expressions as the 'if' and 'else' cases of the ternary operator, and the comma operator theoretically is an expression as,

The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.

So why do I get a syntax error? The comma operator is an expression which should be allowed to be in a conditional operator. Although, putting parentheses around the comma's operands works fine:

a > b ? (console.log(a), a) : b; //Logs and gives a 

Why does that work fine? Parentheses (or the grouping operator) allows the interpreter to know it's dealing with an expression, but console.log(a), a is already an expression without the need of parentheses, so why do I get a syntax error without them?

like image 671
Andrew Li Avatar asked Dec 31 '17 01:12

Andrew Li


People also ask

What is the syntax for a ternary operator JS?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.

What does the comma do in JavaScript?

The comma operator ( , ) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions.

Can you throw an error in a ternary?

No, it's absolutely not allowed. throw is a statement and it can't be part of an expression.

Does JavaScript support ternary operator True or false?

A ternary operator is a three-operand operator that is supported in most programming languages, including JavaScript, Java, C++, C#, and many others. It is also referred to as a conditional operator because it is considered to be a more concise alternative to the conditional ( if-else ) statement.


1 Answers

This is an intentional part of the language, and is outlined in the ECMAScript Language Specification. The syntax for the comma operator is defined in Section 12.16, which states the following:

12.16 Comma Operator ( , )

Syntax

 Expression:   AssignmentExpression   Expression, AssignmentExpression 

Here, the specification outlines how the comma operator is used. An Expression is any AssignmentExpression or itself followed with a comma (the operator) and another AssignmentExpression. The important thing to note is that an AssignmentExpression is an Expression but an Expression is not an AssignmentExpression.

As for the actual conditional operator, the grammar for the operator and conditional expressions is specificed in Section 12.14:

12.14 Conditional Operator ( ? : )

Syntax

 ConditionalExpression:     LogicalORExpression     LogicalORExpression ? AssignmentExpression : AssignmentExpression 

By the specification, a conditional expression can only contain AssignmentExpression s -- not just Expression s. Thus a conditional operator cannot have a comma operator inside one of its operands. This may seem like a weird quirk of language, but there is a specific reason considering the very specific grammar, and per the specification:

NOTE    The grammar for a ConditionalExpression in ECMAScript is slightly different from that in C and Java, which each allow the second subexpression to be an Expression1 but restrict the third expression to be a ConditionalExpression. The motivation for this difference in ECMAScript is to allow an assignment expression to be governed by either arm of a conditional and to eliminate the confusing and fairly useless case of a comma expression as the centre expression.

Because of Java and C's restrictive grammar, they do not allow things like this (Java):

int a = 2; int b = 1; System.out.println(a > b ? b = a : a = b); //Can't use assignment in 'else' part //                                 ^^^^^ 

ECMAScript authors decided to allow for assignment in both branches of the ternary operator, thus this definition with AssignmentExpression occurred. Consequently, this definition also disallows for the comma operator to actually show up in the 'if' part of the conditional operator, but because of its scarcity and uselessness it wasn't a problem. They essentially killed two birds with one stone; allowed for more lenient grammar and got rid of useless syntax that's bad practice.

The reason why adding the grouping operator allows it to work is because the grouping operator production ( Expression ) is by definition also an AssignmentExpression allowing it to be in the ternary operator, see str's answer for more details.


1 This refers to Java's Expression, not ECMAScript's Expression. Java's does not have the comma operator so its Expression does not include it.

like image 176
Andrew Li Avatar answered Sep 21 '22 22:09

Andrew Li