5

我目前正在分析 Javascript 语言。看起来您可以将许多概念分组为称为表达式的基本类型。甚至函数参数和定义也适合该组,以及字符串、数字和数学表达式。唯一不合逻辑的例外是在无意义的相似上下文中的大括号对象表示法。

由于函数由多个表达式组成,因此以下代码是有效的:

function valid(){
    /\W/;
    "ahll";
    var alpha;
    alpha;
    alpha={"first": 90, "second": 80};
    alpha;
    0, {"first": 90, "second": 80};
    [1,2,3];
    alpha;
    2+3;
    new RegExp("/\W/");
    return true;
}

有意以下代码也应该是有效的,但在第二行出现“缺少 ; before statement”语法错误:

function invalid(){
    {"first": 90, "second": 80};
    return true;
}

在接受表达式的所有其他情况下,都接受大括号对象表示法,但也允许大括号代码块的情况除外。

上面提到的语法错误是由javascript的实现还是规范引起的?

这种无意义的表达有更准确的名称吗?

4

5 回答 5

2

上面提到的语法错误是由javascript的实现还是规范引起的?

按规范。

这种无意义的表达有更准确的名称吗

你正在寻找这个词Expression Statement。正如您所说,对象文字是表达式(甚至是主要表达式),就像大多数其他事物一样。它们可以出现在许多上下文中,例如函数参数、运算符的操作数或括号内。

但是,函数体 - 代码 - 不包含表达式,它包含语句。这意味着诸如 if 语句、循环语句或普通块之类的东西。或“表达式语句”,它们只不过是要评估的表达式(并且具有副作用,它们大多不是“废话”)。

但是,规范要求

ExpressionStatement: [前瞻 ∉ { {, function}]Expression ;

注意:ExpressionStatement 不能以左大括号开头,因为这可能会使它与Block模棱两可。此外,ExpressionStatement 不能以 function 关键字开头,因为这可能会使它与 FunctionDeclaration 产生歧义。

于 2014-03-23T13:37:05.677 回答
2

在最后一个示例中,您所查看的对象实际上是一个

来自 MDN:

块语句用于对零个或多个语句进行分组。该块由一对大括号分隔。

因此,基本上,当您启动花括号时,它会将其理解为一个块,并给出错误:

Uncaught SyntaxError: Unexpected token : 

因为它不喜欢它期望语句(等):的块内的那些冒号()。var a = 2它假定大括号后面的内容必须是一组语句,因此看到冒号会感到惊讶,并且在混乱中会引发错误。请注意,这"first": 90不是一个有效的陈述。

那为什么会0, {"first": 90, "second": 80};通过呢?

因为在看到第一个表达式 ( 0),然后是逗号运算符之后,它希望看到另一个类似类型的值(即另一个表达式)。因此它将第二个对象{"first": 90, "second": 80}视为一个对象(也是一个表达式)而不是一个块。

要进一步简化,请尝试{"first": 90, "second": 80}, 0. 请注意,它给出的 SyntaxError 与前一个完全相同。因为,一旦它看到{,它将以下内容视为一个块,并再次抱怨冒号 ( :)。

我该如何避免这种情况?

通过使其成为另一个表达式的一部分,例如:

( {1:2} ) // a block doesn't come inside parentheses
var a = {1 : 2}; // a block can't be the RHS
myFunc( { 1 : 5 } ) // a block can't be a function argument

希望能帮助到你!

于 2014-03-23T12:43:26.990 回答
0

解析器优先将其{视为块的开始而不是对象的开始。

那么我们如何明确地告诉读者在乘法之前先加法,以防出现以下情况:

3 * 4 + 2

也许是这样:

3 * (4 + 2)

同样对于

{"first": 90, "second": 80};

我们可以这样做

({"first": 90, "second": 80}); 

或以解析器了解您的真实意图的各种其他方式。

于 2014-03-23T12:57:49.990 回答
0

这已在上一个问题中解决

花括号用于引入语句块或作为对象文字的开头。为了处理这种歧义,默认情况下,大括号被解释为语句块容器,因此在您的示例中出现语法错误。

当在运算符的 RHS 中使用大括号时,歧义消失了;它是一个对象字面量。

于 2014-03-23T12:44:17.490 回答
0

ECMA-262中定义了许多不同类型的表达式。开头问题中提到的“表达式”与 PrimaryExpression 最匹配,描述如下:(每个缩进行都是一种可能的表示)

PrimaryExpresion:
    this //as the 'this'-keyword
    Identifier //variable or function name ('alpha' in the question)
    Literal //string, number, mathematical expressions
    ArrayLiteral //[1,2,3]
    ObjectLiteral // {"first" : 80}
   ( Expression ) //An expression encapsulated in bracket

花括号代码块:

Block :
    { StatementList_opt } - A list of statements

在这种情况下最相关的声明:

ExpressionStatement :
    [lookahead ∉ {{, function}] Expression ;

这仅允许在开头没有大括号或“function”关键字的表达式。(FunctionDeclarations 与语句和表达式分开,除了作为 FunctionExpression 的 lambda 函数)

Expression 定义不直接指定 PrimaryExpression,但在很长的定义链中,PrimaryExpression 可以被视为 Expression:

Expression:
    AssignmentExpression
    Expression, AssingmentExpression

我确实检查了整个定义链,看看 PrimaryExpression 是否实际上是一个表达式。这是定义链:

Expression:
    AssignmentExpression:
        ConditionalExpression:
            LogicalORExpression:
                LogicalANDExpression:
                    BitwiseORExpression:
                        BitwiseXORExpression:
                            BitwiseANDExpression:
                                EuqalityExpression:
                                    RelationalExpression:
                                        ShiftExpressions:
                                            AdditiveExpression:
                                                MultiplicativeExpression:
                                                    UnaryExpression:
                                                        PostfixExpression:
                                                            LeftHandSideExpression:
                                                                NewExpression:
                                                                    MemberExpression:
                                                                        PrimaryExpression:

回答问题

在ECMA-262中指定为 ObjectLiteral 的大括号对象表示法根据定义在每个表达式中都有效,除非是从语句派生的表达式,因为表达式语句明确禁止将大括号作为表达式的第一个字符出现解决与大括号代码块(定义为块)的冲突。FunctionBody、Block、Program(全局范围)和所有循环构造(IterationStatements)都使用语句,因此在代码部分中只能包含 Blocks 而不是 ObjectLiterals。

最后

该规范限制大括号表示代码块或对象表示法。只要允许使用“var”关键字,大括号就会被视为代码块,反之亦然。

于 2014-03-23T17:45:07.987 回答