Li3*_*357 22 javascript ternary-operator syntax-error language-lawyer ecmascript-6
当我尝试在条件(三元)运算符中使用逗号运算符进行日志记录时,我注意到了一些奇怪的事情.这是一个人为的例子:
const a = 2;
const b = 1;
a > b ? console.log(a), a : b; //I expect this to log and evaluate to aRun Code Online (Sandbox Code Playgroud)
但相反,我遇到了这个:
Uncaught SyntaxError: Unexpected token ,
Run Code Online (Sandbox Code Playgroud)
根据MDN文档,条件运算符接受两个表达式作为三元运算符的"if"和"else"情况,而逗号运算符理论上是表达式,
逗号运算符计算其每个操作数(从左到右)并返回最后一个操作数的值.
那我为什么会出现语法错误?逗号运算符是一个表达式,应该允许它在条件运算符中.虽然,在逗号的操作数周围加括号可以正常工作:
a > b ? (console.log(a), a) : b; //Logs and gives a
Run Code Online (Sandbox Code Playgroud)
为什么这样可行?圆括号(或分组运算符)允许解释者知道它在处理一个表达式,但console.log(a), a是已经无需括号的表达,所以为什么我得到一个语法错误,没有他们?
Li3*_*357 29
这是该语言的有意部分,并在ECMAScript语言规范中进行了概述.逗号运算符的语法在第12.16节中定义,其中说明了以下内容:
12.16逗号运算符(,)
句法
Expression: AssignmentExpression Expression, AssignmentExpression
这里,规范概述了如何使用逗号运算符.An Expression是AssignmentExpression逗号(运算符)和其他符号的任意或本身AssignmentExpression.需要注意的重要一点是,一个AssignmentExpression是一个Expression,但一个Expression是没有的AssignmentExpression.
对于实际的条件运算符,运算符和条件表达式的语法在12.14节中具体说明:
12.14条件运算符(?:)
句法
ConditionalExpression: LogicalORExpression LogicalORExpression ? AssignmentExpression : AssignmentExpression
根据规范,条件表达式只能包含AssignmentExpressions - 而不仅仅是Expressions.因此,条件运算符不能在其操作数之一中包含逗号运算符.这可能看起来像一个奇怪的语言怪癖,但有一个特定的原因考虑非常具体的语法,并按照规范:
注意
ConditionalExpressionECMAScript中的语法与C和Java中的语法略有不同,每个语法允许第二个子表达式为1,但将第三个表达式限制为a .ECMAScript中这种差异的动机是允许赋值表达式由条件的任一臂控制,并消除逗号表达式作为中心表达式的混乱且相当无用的情况.ExpressionConditionalExpression
由于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
// ^^^^^
Run Code Online (Sandbox Code Playgroud)
ECMAScript作者决定允许在三元运算符的两个分支中进行赋值,从而AssignmentExpression发生了这个定义.因此,这个定义也不允许逗号运算符实际显示在条件运算符的"if"部分,但由于它的稀缺性和无用性,它不是问题.他们基本上一石二鸟; 允许更宽松的语法,并摆脱无用的语法,这是不好的做法.
添加分组运算符允许它工作的原因是因为分组运算符生成( Expression )根据定义也AssignmentExpression允许它在三元运算符中,请参阅str的答案以获取更多详细信息.
1这是指JavaExpression,而不是ECMAScript Expression.Java的确实不具备逗号操作符所以它 Expression不包括它.