在 Firefox 3.5 中,我在 Firebug 控制台中输入:
false=={} // => evals to false
{}==false // syntax error
对此有何解释?
在 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>]
IE。在没有大括号的单一语句形式中。然后,它允许您在可以使用单个语句的任何地方使用语句块,这意味着您可以使用 if-braces-many-statements。但这也意味着您可以拥有自己的语句块,而无需关联的流控制语句。
这绝对没有实际用途!你可能会认为它给了你信息隐藏,但不是:
var a= 1;
{
var a= 2;
}
alert(a);
...导致2
,因为语句块本身不会创建新范围。
JavaScript 以这种方式定义流控制和语句块,因为 C(以及从它派生的其他语言)就是这样做的。但是,这些语言并没有{}
作为 Object 文字表达式提供双重职责,因此它们没有使这成为另一个 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
我不确定列表顺序是否重要(这就是它们在规范中的方式),但是......对象文字是一个 ExpressionStatement,标准说明如下(第 12.4 节):
请注意,ExpressionStatement 不能以左大括号开头,因为这可能会使它与 Block 产生歧义。此外,ExpressionStatement 不能以 function 关键字开头,因为这可能会使它与 FunctionDeclaration 产生歧义。
所以我们可以在程序的开头有一个表达式,但它不能以左大括号 ( {
) 开头。这就是为什么以下工作正常:
({} == false);
alert({} == false);
!{} == false;
简单的说,{}==false
都是js编译成的{};==false
,所以是语法错误。你应该写({})==false
,它会返回假。