如何解析和解释以下表达式?Chrome控制台是这样做的:
> {'foo'}{'bar'} 'bar'
并且类似地
> {a: 'foo'}{b: 'bar'} 'bar'
(显然,这里发生的任何事情都不应该在真实的代码中使用。)
soat7uwm1#
您可以使用AST Explorer查看AST详细信息。代码1:
{'foo'}{'bar'}
AST:
[ { "type": "BlockStatement", "start": 0, "end": 7, "body": [ { "type": "ExpressionStatement", "start": 1, "end": 6, "expression": { "type": "Literal", "start": 1, "end": 6, "value": "foo", "raw": "'foo'" } } ] }, { "type": "BlockStatement", "start": 7, "end": 14, "body": [ { "type": "ExpressionStatement", "start": 8, "end": 13, "expression": { "type": "Literal", "start": 8, "end": 13, "value": "bar", "raw": "'bar'" } } ] } ]
也就是说两个街区代码2:
{a: 'foo'}{b: 'bar'}
[ { "type": "BlockStatement", "start": 0, "end": 10, "body": [ { "type": "LabeledStatement", "start": 1, "end": 9, "body": { "type": "ExpressionStatement", "start": 4, "end": 9, "expression": { "type": "Literal", "start": 4, "end": 9, "value": "foo", "raw": "'foo'" } }, "label": { "type": "Identifier", "start": 1, "end": 2, "name": "a" } } ] }, { "type": "BlockStatement", "start": 10, "end": 20, "body": [ { "type": "LabeledStatement", "start": 11, "end": 19, "body": { "type": "ExpressionStatement", "start": 14, "end": 19, "expression": { "type": "Literal", "start": 14, "end": 19, "value": "bar", "raw": "'bar'" } }, "label": { "type": "Identifier", "start": 11, "end": 12, "name": "b" } } ] } ]
所以这意味着两个块有两个labels。
t98cgbkg2#
第一个语句可以重写为
{ 'foo'; } { 'bar'; }
也就是说,两个单独的块语句,每个语句都包含一个常量字符串。结果是解释此代码时计算的最后一个表达式,即'bar'。第二个语句可以类似地重写为
'bar'
{ a: 'foo'; } { b: 'bar'; }
其中a和b是labels,可用于代码中的有限跳转(通常用于退出嵌套循环中的内部循环)。同样,它的值为'bar'。虽然第二个语句看起来有点类似于对象字面量,但事实并非如此。请注意,> {b: 'bar', a: 'foo'}会导致语法错误:未捕获的语法错误:意外令牌:':'正如Pointy在注解中所观察到的,当解释器遇到一个以{开头的语句时,它可能属于一个对象文字或一个代码块,它会一致地将其解释为一个代码块。所有符合规范的解析器都是这样吗?让我们假设js grammar contributed to Antlr4是正确的(根据评论,它是为ES 2020更新的)。在Antlr 4中,任何先指定的规则都优先于后面的规则。我们发现(从链接的语法中复制并粘贴相关规则):
a
b
> {b: 'bar', a: 'foo'}
{
program : HashBangLine? sourceElements? EOF ; sourceElement : statement ; statement : block | variableStatement | importStatement | exportStatement | emptyStatement_ | classDeclaration | functionDeclaration | expressionStatement | ifStatement | iterationStatement | continueStatement | breakStatement | returnStatement | yieldStatement | withStatement | labelledStatement | switchStatement | throwStatement | tryStatement | debuggerStatement ; expressionStatement : {this.notOpenBraceAndNotFunction()}? expressionSequence eos ; expressionSequence : singleExpression (',' singleExpression)* ; singleExpression # ...snipped many lines... | objectLiteral # ObjectLiteralExpression | '(' expressionSequence ')' # ParenthesizedExpression ;
因此,假设这个语法是正确的,JS将总是将打开的{ s解释为块,因为block在statement中出现的时间比expressionStatement早得多(这导致objectLiteral通过expressionSequences-> singleExpression-> objectLiteral)。
block
statement
expressionStatement
objectLiteral
expressionSequences
singleExpression
2条答案
按热度按时间soat7uwm1#
您可以使用AST Explorer查看AST详细信息。
代码1:
AST:
也就是说两个街区
代码2:
AST:
所以这意味着两个块有两个labels。
t98cgbkg2#
第一个语句可以重写为
也就是说,两个单独的块语句,每个语句都包含一个常量字符串。结果是解释此代码时计算的最后一个表达式,即
'bar'
。第二个语句可以类似地重写为
其中
a
和b
是labels,可用于代码中的有限跳转(通常用于退出嵌套循环中的内部循环)。同样,它的值为'bar'
。虽然第二个语句看起来有点类似于对象字面量,但事实并非如此。请注意,> {b: 'bar', a: 'foo'}
会导致语法错误:未捕获的语法错误:意外令牌:':'
正如Pointy在注解中所观察到的,当解释器遇到一个以
{
开头的语句时,它可能属于一个对象文字或一个代码块,它会一致地将其解释为一个代码块。所有符合规范的解析器都是这样吗?让我们假设js grammar contributed to Antlr4是正确的(根据评论,它是为ES 2020更新的)。在Antlr 4中,任何先指定的规则都优先于后面的规则。我们发现(从链接的语法中复制并粘贴相关规则):因此,假设这个语法是正确的,JS将总是将打开的
{
s解释为块,因为block
在statement
中出现的时间比expressionStatement
早得多(这导致objectLiteral
通过expressionSequences
->singleExpression
->objectLiteral
)。