正如您可能知道的那样,ECMAscript会尝试变聪明,并且如果您没有明确地编写分号,则会自动插入分号。简单的例子
function foo() {
var bar = 5
return bar
}
仍将按预期工作。但如果你依赖它,有一些警告。如果我们像这样重写那个函数
function foo() {
var bar = 5
return
{
bar: bar
}
}
..该函数现在将返回undefined
,因为解释器会在return
语句之后插入该分号(这就是为什么你总是应该在同一行上带一个大括号作为语句的原因)
然而,了解所有这些我现在想知道如何安全如下所示的return
语句,跨浏览器和版本
function foo() {
var a = true,
b = true,
c = false;
return a
&& b
&& c;
}
我刚在生产环境中写了一个类似的return statement
。仅仅因为我知道ECMAscript的“问题”对分号插入不太明智我现在想知道,如果该代码100%工作。在我对FF / Chrome / IE(最新版本)的第一次测试中,这似乎完全没问题,但它真的是吗?
如果除了该行中的return
语句之外还有其他内容,自动分号插入是否会“唤醒”?任何人都可以提供有关此的实现级详细信息吗?
答案 0 :(得分:12)
javascript解释器/编译器非常聪明,只有在有了有效的Javascript之后才插入自动分号。
您的代码有效,因为&& b
不是有效的表达式 - 这就是为什么在return a
之后没有插入分号的原因:
return a && b && c;
然而:
return (undefined);//implicitely inserted
{
....
}
完全有效,这就是分号插入的原因。
为了完整性,参考规范:automatic semicolon insertion。这些例子值得一读。
答案 1 :(得分:2)
不是特定于浏览器/实施,但ECMAScript Language Specification的Section 7.9 Automatic Semicolon Insertion
值得一读。
7.9自动分号插入
某些ECMAScript语句(空语句,变量语句,表达式语句,do-while 语句,继续语句,break语句,return语句和throw语句)必须是 以分号结束。此类分号可能始终显式出现在源文本中。对于 然而,在某些情况下,可以从源文本中省略这样的分号。这些 通过说分号自动插入源代码令牌来描述情况 在这些情况下流。
7.9.1自动分号插入规则 分号插入有三个基本规则:
当从左到右解析程序时,会遇到一个令牌(称为违规令牌) 语法的任何产生都不允许,然后在分配之前自动插入分号 如果满足下列一个或多个条件,则会触犯令牌:
当从左到右解析程序时,会遇到令牌输入流的末尾 并且解析器无法将输入令牌流解析为单个完整的ECMAScript程序 分号将自动插入输入流的末尾。
当从左到右解析程序时,会遇到某些人允许的令牌 生产语法,但生产是限制生产,令牌将是第一个 紧跟注释后终端或非终端的令牌?[此处没有LineTerminator]?在...内 限制生产(因此这种令牌称为受限令牌),受限制的令牌是 通过至少一个LineTerminator与前一个标记分开,然后自动分号 在限制令牌之前插入。 但是,前面的规则还有一个重要的条件:永远不会插入分号 自动,如果分号将被解析为空语句或分号将成为 for语句标题中的两个分号之一(见12.6.3)。 注意以下是语法中唯一受限制的产品: PostfixExpression: LeftHandSideExpression [此处没有LineTerminator] ++ LeftHandSideExpression [此处没有LineTerminator] - ContinueStatement: 继续[此处没有LineTerminator]标识符; BreakStatement: break [此处没有LineTerminator]标识符; ReturnStatement: 返回[此处没有LineTerminator]表达式; 投掷声明: 抛出[此处没有LineTerminator]表达式; 这些限制性作品的实际效果如下: 当遇到++或 - token时,解析器将其视为后缀运算符,并且至少有一个 LineTerminator发生在前一个令牌和++或 - 令牌之间,然后是一个分号 在++或 - token之前插入。 当遇到continue,break,return或throw标记并且之前遇到LineTerminator时 下一个标记,在continue,break,return或throw标记之后自动插入分号。 由此产生的对ECMAScript程序员的实用建议是: 后缀++或 - 运算符应与其操作数出现在同一行。 return或throw语句中的表达式应该与return或throw标记在同一行开始。 中断或继续语句中的标识符应与中断或继续令牌位于同一行。
7.9.2自动分号插入示例
来源
{ 1 2 } 3
即使使用自动分号插入规则,也不是ECMAScript语法中的有效句子。在 对比,来源
{ 1
2 } 3
也不是有效的ECMAScript语句,而是通过自动分号插入转换为 以下内容:
{ 1
;2 ;} 3;
这是一个有效的ECMAScript句子。 来源
for (a; b
)
不是有效的ECMAScript语句,并且不会被自动分号插入更改,因为 for语句的标题需要分号。自动分号插入永远不会插入其中一个 for语句标题中的两个分号。 来源
return
a + b
通过自动分号插入转换为以下内容:
return;
a + b;
注意表达式a + b不被视为return语句返回的值,因为a LineTerminator将它与令牌返回分开。 来源
a = b
++c
通过自动分号插入转换为以下内容:
a = b;
++c;
注意:令牌++不被视为应用于变量b的后缀运算符,因为会出现LineTerminator 在b和++之间。 来源
if (a > b)
else c = d
不是有效的ECMAScript语句,并且在else标记之前不会被自动分号插入更改, 即使在那时没有生成语法,因为自动插入分号 然后将被解析为空语句。 来源
a = b + c
(d + e).print()
不会通过自动分号插入进行转换,因为以括号开头的表达式开头 第二行可以解释为函数调用的参数列表:
a = b + c(d + e).print()
在赋值语句必须以左括号开头的情况下,对于它来说是一个好主意 程序员在前面的语句末尾提供一个显式分号而不是依赖 自动分号插入。
答案 2 :(得分:0)
正如Christoph指出的那样,您的return语句将在所有浏览器中正常运行。我更愿意让它变得更加明确,如果不是为了计算机而是为了人类,至少通过以不同的方式放置和运算符:
return a &&
b &&
c;
在这种情况下,没有人需要花费一秒钟,想知道自动分号是否会造成严重破坏。我只喜欢这个用于JavaScript,您的原始代码更容易阅读。