首页 文章

为什么三元运算符中的逗号会在JavaScript中引发语法错误?

提问于
浏览
23

当我尝试在条件(三元)运算符中使用逗号运算符进行日志记录时,我注意到了一些奇怪的事情 . 这是一个人为的例子:

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,条件运算符接受两个表达式作为三元运算符的'if'和'else'情况,comma operator理论上是表达式,

逗号运算符计算其每个操作数(从左到右)并返回最后一个操作数的值 .

那我为什么会出现语法错误?逗号运算符是一个表达式,应该允许它在条件运算符中 . 虽然,在逗号的操作数周围加括号可以正常工作:

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

为什么这样可行?括号(或grouping operator)允许解释器知道它正在处理表达式,但 console.log(a), a 已经是一个表达式而不需要括号,那么为什么没有它们会出现语法错误?

2 回答

  • 29

    这是该语言的有意识部分,并在ECMAScript Language Specification中进行了概述 . 逗号运算符的语法在Section 12.16中定义,其中声明了以下内容:

    12.16逗号运算符(,)语法表达式:
    AssignmentExpression
    表达,AssignmentExpression

    这里,规范概述了如何使用逗号运算符 . Expression 是任何 AssignmentExpression 或其后跟一个逗号(运算符)和另一个 AssignmentExpression . 需要注意的重要一点是 AssignmentExpressionExpression 但是 Expressionnot AssignmentExpression .

    对于实际的条件运算符,运算符和条件表达式的语法在Section 12.14中具体说明:

    12.14条件运算符(?:)语法ConditionalExpression:
    LogicalORExpression
    LogicalORExpression? AssignmentExpression:AssignmentExpression

    根据规范,条件表达式只能包含 AssignmentExpression s - 而不仅仅是 Expression s . 因此,条件运算符不能在其操作数之一中包含逗号运算符 . 这可能看起来像一个奇怪的语言怪癖,但有一个特定的原因考虑非常具体的语法,并按照规范:

    注意ECMAScript中ConditionalExpression的语法与C和Java中的语法稍有不同,每个语法都允许第二个子表达式为Expression1,但将第三个表达式限制为ConditionalExpression . ECMAScript中这种差异的动机是允许赋值表达式由条件的任一臂控制,并消除逗号表达式作为中心表达式的混乱且相当无用的情况 .

    由于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 ) 根据定义也允许它在三元运算符中,有关详细信息,请参阅str's answer .


    1这是指Java的 Expression ,而不是ECMAScript的 Expression . Java的 not 有逗号运算符,因此 Expression 不包含它 .

  • 1

    这个答案是Li357's answer的扩展 . 具体来说,条件运算符允许 PrimaryExpression (不包括逗号运算符)而不是 Expression (包括逗号运算符)的语法中的位置 .


    请参阅本答案底部每个提到的表达式或运算符的规范链接 .

    条件运算符的规范定义如下:

    ConditionalExpression:
    LogicalORExpression
    LogicalORExpression? AssignmentExpression:AssignmentExpression

    因此,它可以是 LogicalORExpression ,也可以是 LogicalORExpression 和两个 AssignmentExpression 的组合 . 除其他外, AssignmentExpression 本身也可以由 LogicalORExpression 指定 .

    但与其简单的声音名称不同, LogicalORExpression 不仅仅是一个基本条件,而且可以由许多不同的嵌套表达式组成 . 一直到下来 PrimaryExpression 其中还包括分组表达式 (Expression) .

    并且可以在逗号运算符的规范中看到,它仅在 Expression 中指定,但在 PrimaryExpression 本身中不指定 .

    表达:
    AssignmentExpression
    表达,AssignmentExpression

    用简单的词汇总结一下:JavaScript的语法只允许 AssignmentExpression 中的逗号运算符包含在分组运算符 () 中 .

    另见Operator Precedence in JavaScript .

    资源

相关问题