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

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


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.


This answer is meant as an extension of Li357's answer. Specifically to show where in the grammar the Conditional Operator allows PrimaryExpressions (which does not include the Comma Operator) but not Expressions (which does include the Comma Operator).


Please see the links to the specification for every mentioned type of expression or operator on the bottom of this answer.

The specification of the Conditional Operator is defined as follows:

ConditionalExpression:  LogicalORExpression  LogicalORExpression ? AssignmentExpression : AssignmentExpression

Thus it can be either a LogicalORExpression only, or a combination of LogicalORExpression and two AssignmentExpressions. An AssignmentExpression itself can, among other things, be specified by a LogicalORExpression as well.

But unlike its simple sounding name, the LogicalORExpression is not just a basic condition but can consist of many, many different nested expressions itself.All the way down to PrimaryExpression which also includes grouped expressions (Expression).

And as can be seen in the specification of the Comma Operator, it is only specified in Expression, but not in PrimaryExpression itself.

Expression:  AssignmentExpression  Expression , AssignmentExpression

To summarize it in simpler words: The grammar of JavaScript only allows the comma operator within an AssignmentExpression if it is contained within a grouping operator ().

Also see the Operator Precedence in JavaScript.

Resources