JavaScript:{} == false是一个SyntaxError?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (21)

在Firefox 3.5中,我在Firebug控制台中输入:

false=={} // => evals to false
{}==false // syntax error

这是什么解释?

提问于
用户回答回答于
{

在语句开始时发送一个'语句块'(见ECMA-262-3第12.1节),其中包含语句列表。

}

立即结束没有语句的语句块。没关系。但是现在解析器正在寻找下一个语句:

==false

咦?这不是一个声明; 语法错误。

什么是语句块?那么,每当你说:你正在写一个语句块

if (something) {
    ...
}

JavaScript将这些流控制语句定义为:

if "(" <expression> ")" <statement> [else <statement>]

即。在没有大括号的单一陈述形式中。然后它允许您在任何可以使用单个语句的地方使用语句块,这意味着您可以拥有if-braces-many-statements。但这也意味着您可以拥有一个独立的语句块,并且没有关联的流控制语句。

这绝对没有实际的目的!你可能会想,它会给你隐藏信息,但不会:

var a= 1;
{
    var a= 2;
}
alert(a);

...结果2,因为语句块本身不会创建新的范围。

JavaScript以这种方式定义流控制和语句块,因为C(以及从中派生出的其他语言)都这样做了。这些语言虽然并没有把{}对象字面表达式当成双重任务,所以他们没有模棱两可使得这又成了JS的错误。

即使是这种崇拜 - 文字:

{
   a: 1
}

是一个有效的语句块,因为':'用于表示语句中的标签。(并且1是一个无用的表达式语句,省略了分号。)标签是C中很少使用的另一个继承自JavaScript的特性。它们并不像街区那样完全没有意义,但它们很少被需要,而且通常被认为味道不好。

(具有两个属性的文字将导致语法错误,因为对象文字使用逗号分隔符,但带标签的语句必须用分号分隔。)

不是唯一一个 JavaScript的松散语法可以通过对你认为是表达式的东西进行其他表述而让你感到惊讶的地方。

用户回答回答于

好的,我已经学习了ECMAScript规范(PDF),并且我有一个关于BNF语法的解释。

从主符号开始解析ECMAScript源文件,名为Program

Program:
    SourceElements

SourceElements'(递归)定义是这样的:

SourceElements :
    SourceElement
    SourceElements SourceElement

SourceElement被定义为:

SourceElement :
    Statement
    FunctionDeclaration

我们感兴趣的是对象字面值语法,所以我们忽略FunctionDeclaration并查看Statement符号:

Statement :
    Block
    VariableStatement
    EmptyStatement
    ExpressionStatement
    IfStatement
    IterationStatement
    ContinueStatement
    BreakStatement
    ReturnStatement
    WithStatement
    LabelledStatement
    SwitchStatement
    ThrowStatement
    TryStatement

我不确定列表顺序是否重要(这是他们在规范中的样子),但是......对象字面量是一个表达式语句,标准说明如下(第12.4节):

请注意,ExpressionStatement不能以开头大括号开头,因为这可能会使它与Block不明确。此外,ExpressionStatement不能以function关键字开头,因为这可能会使其与FunctionDeclaration模糊不清。

所以我们可能会在程序开始时有一个表达式,但它不能以开头大括号({)开始。这就是为什么以下工作正常:

  • ({} == false);
  • alert({} == false);
  • !{} == false;

扫码关注云+社区