大括号对象表示法在任何表达式中是否有效?

时间:2014-03-23 12:34:44

标签: javascript expression javascript-objects curly-brackets

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

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

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;
}

根据意图,下面的代码也应该有效,但是缺少一个"在陈述之前#34;第二行的语法错误:

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

在接受表达式的每个其他情况下都接受大括号对象表示法,除了这些允许使用大括号代码块的情况。

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

这种无意义的表达是否有更精确的名称?

5 个答案:

答案 0 :(得分:2)

在最后一个示例中,您作为对象查看的内容实际上是block

来自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

希望它有所帮助!

答案 1 :(得分:2)

  

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

按规格。

  

这种无意义的表达是否有更精确的名称

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

但是,函数体 - 代码 - 不包含表达式,它由statements组成。这意味着if语句,循环语句或普通块等。或者“表达式陈述”,它们只是一个待评估的表达式(并且有副作用,它们大多不是“废话”)。

然而,the spec mandates

  
    

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

  
     

注意:ExpressionStatement不能以开头卷曲开头   因为这可能会使Block模糊不清。还有,一个   ExpressionStatement不能以function关键字开头,因为   这可能会使FunctionDeclaration模糊不清。

答案 2 :(得分:0)

上一个问题here

已经解决了这个问题

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

当在操作员的RHS中使用花括号时,模糊性消失;它是一个对象文字。

答案 3 :(得分:0)

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

那么我们该做什么来明确地告诉读者在乘法之前首先添加,如果:

3 * 4 + 2

也许这就是:

3 * (4 + 2)

同样适用于

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

我们可以这样做

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

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

答案 4 :(得分: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

Curly括号代码块:

Block :
    { StatementList_opt } - A list of statements

本案中最相关的声明:

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

这只允许表达式在开头不带开头花括号或'function'关键字。 (FunctionDeclarations与语句和表达式分开,除了作为FunctionExpression的lambda函数)

表达式定义不直接指定PrimaryExpression,但是在一长串定义中,PrimaryExpression可以被视为Expression:

Expression:
    AssignmentExpression
    Expression, AssingmentExpression

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

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

回答问题

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

最后

规范限制大括号表示代码块或对象表示法。大括号被视为代码块,只要允许使用'var'-keyword,反之亦然。