为什么三元运算符中的这个逗号会在 JavaScript 中引发语法错误?
Why does this comma inside a ternary operator throw a syntax error in JavaScript?
尝试在条件(三元)运算符中使用逗号运算符进行日志记录时,我发现有些奇怪。这是一个人为的例子:
const a = 2;
const b = 1;
a > b ? console.log(a), a : b; //I expect this to log and evaluate to a
但我却遇到了这个:
Uncaught SyntaxError: Unexpected token ,
根据MDN documentation, the conditional operator accepts two expressions as the 'if' and 'else' cases of the ternary operator, and the comma operator理论上是一个表达式,
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
那么为什么我会收到语法错误?逗号运算符是一个表达式,应该允许它出现在条件运算符中。虽然,将括号放在逗号的操作数两边效果很好:
a > b ? (console.log(a), a) : b; //Logs and gives a
为什么这样可以正常工作?括号(或 grouping operator)允许解释器 知道 它正在处理一个表达式,但是 console.log(a), a
已经 一个不需要括号的表达式,为什么没有括号我会出现语法错误?
这是语言的有意部分,在 ECMAScript Language Specification. The syntax for the comma operator is defined in Section 12.16 中进行了概述,其中说明如下:
12.16 Comma Operator ( , )
Syntax
Expression:
AssignmentExpression
Expression, AssignmentExpression
此处,规范概述了逗号运算符的使用方式。 Expression
是任何 AssignmentExpression
或其本身后跟逗号(运算符)和另一个 AssignmentExpression
。需要注意的重要一点是 AssignmentExpression
是 Expression
而 Expression
是 不是 一个 AssignmentExpression
.
至于实际的条件运算符,运算符和条件表达式的语法在Section 12.14:
12.14 Conditional Operator ( ? : )
Syntax
ConditionalExpression:
LogicalORExpression
LogicalORExpression ? AssignmentExpression : AssignmentExpression
根据规范,条件表达式只能包含 AssignmentExpression
-- 而不仅仅是 Expression
秒。因此,条件运算符不能在其操作数之一中包含逗号运算符。这似乎是一种奇怪的语言怪癖,但考虑到非常具体的语法和规范,有一个特定的原因:
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 Expression
1 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.
由于 Java 和 C 的限制性语法,他们不允许这样的事情 (Java):
int a = 2;
int b = 1;
System.out.println(a > b ? b = a : a = b); //Can't use assignment in 'else' part
// ^^^^^
ECMAScript 作者决定允许在三元运算符的两个分支中进行赋值,因此出现了 AssignmentExpression
的定义。因此,这个定义也不允许逗号运算符实际出现在条件运算符的 'if' 部分,但由于它的稀缺性和无用性,这不是问题。他们基本上用一块石头杀死了两只鸟;允许更宽松的语法并摆脱无用的语法,这是不好的做法。
添加分组运算符允许它工作的原因是因为分组运算符生产 ( Expression )
根据定义也是一个 AssignmentExpression
允许它在三元运算符中,有关详细信息,请参阅 。
1这里指的是Java的Expression
,不是ECMAScript的Expression
。 Java 确实 没有 有逗号运算符,所以它的 Expression
不包括它。
这个答案是 的延伸。专门用于显示语法中条件运算符允许 PrimaryExpression
s(不包括逗号运算符)但不允许 Expression
s(包括逗号运算符)的位置。
请参阅此答案底部提到的每种表达式或运算符的规范链接。
条件运算符的规范定义如下:
ConditionalExpression:
LogicalORExpression
LogicalORExpression ? AssignmentExpression : AssignmentExpression
因此它可以是一个 LogicalORExpression
,也可以是 LogicalORExpression
和两个 AssignmentExpression
的组合。 AssignmentExpression
本身也可以由 LogicalORExpression
指定。
但与其听起来简单的名称不同,LogicalORExpression
不仅仅是一个基本条件,它本身还可以包含很多很多不同的嵌套表达式。
一直到 PrimaryExpression
,其中还包括分组表达式 (Expression)
.
并且在逗号运算符的规范中可以看出,它只在Expression
中指定,而在PrimaryExpression
本身中没有指定。
Expression:
AssignmentExpression
Expression , AssignmentExpression
用更简单的话概括一下:JavaScript 的语法只允许 AssignmentExpression
中包含逗号运算符,前提是它包含在分组运算符 ()
.[=43= 中]
另见 Operator Precedence in JavaScript。
资源
尝试在条件(三元)运算符中使用逗号运算符进行日志记录时,我发现有些奇怪。这是一个人为的例子:
const a = 2;
const b = 1;
a > b ? console.log(a), a : b; //I expect this to log and evaluate to a
但我却遇到了这个:
Uncaught SyntaxError: Unexpected token ,
根据MDN documentation, the conditional operator accepts two expressions as the 'if' and 'else' cases of the ternary operator, and the comma operator理论上是一个表达式,
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
那么为什么我会收到语法错误?逗号运算符是一个表达式,应该允许它出现在条件运算符中。虽然,将括号放在逗号的操作数两边效果很好:
a > b ? (console.log(a), a) : b; //Logs and gives a
为什么这样可以正常工作?括号(或 grouping operator)允许解释器 知道 它正在处理一个表达式,但是 console.log(a), a
已经 一个不需要括号的表达式,为什么没有括号我会出现语法错误?
这是语言的有意部分,在 ECMAScript Language Specification. The syntax for the comma operator is defined in Section 12.16 中进行了概述,其中说明如下:
12.16 Comma Operator ( , )
Syntax
Expression: AssignmentExpression Expression, AssignmentExpression
此处,规范概述了逗号运算符的使用方式。 Expression
是任何 AssignmentExpression
或其本身后跟逗号(运算符)和另一个 AssignmentExpression
。需要注意的重要一点是 AssignmentExpression
是 Expression
而 Expression
是 不是 一个 AssignmentExpression
.
至于实际的条件运算符,运算符和条件表达式的语法在Section 12.14:
12.14 Conditional Operator ( ? : )
Syntax
ConditionalExpression: LogicalORExpression LogicalORExpression ? AssignmentExpression : AssignmentExpression
根据规范,条件表达式只能包含 AssignmentExpression
-- 而不仅仅是 Expression
秒。因此,条件运算符不能在其操作数之一中包含逗号运算符。这似乎是一种奇怪的语言怪癖,但考虑到非常具体的语法和规范,有一个特定的原因:
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 anExpression
1 but restrict the third expression to be aConditionalExpression
. 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.
由于 Java 和 C 的限制性语法,他们不允许这样的事情 (Java):
int a = 2;
int b = 1;
System.out.println(a > b ? b = a : a = b); //Can't use assignment in 'else' part
// ^^^^^
ECMAScript 作者决定允许在三元运算符的两个分支中进行赋值,因此出现了 AssignmentExpression
的定义。因此,这个定义也不允许逗号运算符实际出现在条件运算符的 'if' 部分,但由于它的稀缺性和无用性,这不是问题。他们基本上用一块石头杀死了两只鸟;允许更宽松的语法并摆脱无用的语法,这是不好的做法。
添加分组运算符允许它工作的原因是因为分组运算符生产 ( Expression )
根据定义也是一个 AssignmentExpression
允许它在三元运算符中,有关详细信息,请参阅
1这里指的是Java的Expression
,不是ECMAScript的Expression
。 Java 确实 没有 有逗号运算符,所以它的 Expression
不包括它。
这个答案是 PrimaryExpression
s(不包括逗号运算符)但不允许 Expression
s(包括逗号运算符)的位置。
请参阅此答案底部提到的每种表达式或运算符的规范链接。
条件运算符的规范定义如下:
ConditionalExpression: LogicalORExpression LogicalORExpression ? AssignmentExpression : AssignmentExpression
因此它可以是一个 LogicalORExpression
,也可以是 LogicalORExpression
和两个 AssignmentExpression
的组合。 AssignmentExpression
本身也可以由 LogicalORExpression
指定。
但与其听起来简单的名称不同,LogicalORExpression
不仅仅是一个基本条件,它本身还可以包含很多很多不同的嵌套表达式。
一直到 PrimaryExpression
,其中还包括分组表达式 (Expression)
.
并且在逗号运算符的规范中可以看出,它只在Expression
中指定,而在PrimaryExpression
本身中没有指定。
Expression: AssignmentExpression Expression , AssignmentExpression
用更简单的话概括一下:JavaScript 的语法只允许 AssignmentExpression
中包含逗号运算符,前提是它包含在分组运算符 ()
.[=43= 中]
另见 Operator Precedence in JavaScript。