我目前正在分析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的实现还是规范引起的?
这种无意义的表达是否有更精确的名称?
答案 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语句,循环语句或普通块等。或者“表达式陈述”,它们只是一个待评估的表达式(并且有副作用,它们大多不是“废话”)。
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,反之亦然。