自动插入分号和return语句[复制](Automatic semicolon insertion

2019-06-18 11:14发布

这个问题已经在这里有一个答案:

  • 什么是JavaScript的自动分号插入(ASI)的规则? 4个回答

正如你可能知道,EcmaScript的尝试是聪明的,并会自动插入分号 ,如果你不写那些明确。 简单的例子

function foo() {
    var bar = 5

    return bar
}

如预期仍然可以工作。 但也有一些注意事项,如果你依靠这一点。 如果我们重新编写等,使得功能

function foo() {
    var bar = 5

    return
    {
        bar: bar
    }
}

..that函数现在将返回undefined ,因为解释将在之后插入分号return声明(这是一个理由,为什么你总是应该把在同一行花括号作为语句)。

然而,知道这一切我现在不知道怎么一个安全的 return ,如下面的语句,跨浏览器和版本

function foo() {
    var a = true,
        b = true,
        c = false;

    return a 
            && b
            && c;
}

我只写了一个类似return statement在生产环境中。 只是因为我知道有关“问题”的ECMAScript beeing不那么聪明分号插入我现在想知道,如果代码工作100%。 在我的FF /铬/ IE(最新版本)第一次测试,这似乎是完全正常的,但真的是这样吗?

是否自动插入分号 “唤醒”,如果有任何东西,但在return该行语句? 任何人都可以提供实现层次的细节这件事吗?

Answer 1:

JavaScript解释器/编译器是如此聪明,只能插入自动分号之后是否有有效的JavaScript。

你的代码的工作,因为&& b ,因为它代表没有有效的表达-这就是为什么没有分号获取插入后return a导致:

return a && b && c;

然而:

return (undefined);//implicitely inserted
{
    ....
}

是完全有效的,这就是为什么一个分号被插入。

为完整起见裁判的规格: 自动分号插入 。 这些例子都值得一读通过。



Answer 2:

没有浏览器/ implentation具体,但Section 7.9 Automatic Semicolon Insertion的的ECMAScript语言规范是值得一读。

7.9自动分号插入

某些ECMAScript的语句(空语句,变量语句,表达式语句,do-while语句,continue语句,break语句,return语句和throw语句)必须以分号结束。 这些分号总是可以明确地出现在源文本。 为了方便起见,然而,这样的分号可以从在某些情况下的源文本中省略。 这些情况通过说,分号被自动插入到在这些情况下的源代码令牌流中描述。

自动分号插入7.9.1规则有分号插入的三条基本原则:

  1. 时,作为上述程序的从左至右解析,当遇到一个令牌(称为违规令牌)未被任何生产语法的允许,则分号自动违规令牌之前,如果一个或多个下面的插入条件为真:

    • 有问题的令牌从令牌以前由至少一个LineTerminator分离。
    • 违规的令牌}。
  2. 时,作为上述程序的从左至右解析,当遇到令牌的输入流的结束和解析器是无法解析输入令牌流作为一个单一的完整的ECMAScript程序,然后分号自动在的端插入的输入流。

  3. 时,作为上述程序的从左至右解析,当遇到标记由一些生产语法的允许的,但生产是受限的生产和令牌将是一个终端的第一个标记或非终结立即注释以下?[在这里没有LineTerminator] 受限的生产中(并且因此这样的令牌被称为受限令牌),且限制令牌从令牌以前由至少一个LineTerminator分离,然后分号被自动限制令牌之前插入。 然而,存在于上述规则的附加重载条件:分号从不插入如果自动分号将被解析为一个空的语句或者,如果该分号将成为for语句的报头中的两个分号之一(见12.6.3)。 注:以下是语法的只限于生产:PostfixExpression:LeftHandSideExpression [这里没有LineTerminator] ++ LeftHandSideExpression [这里没有LineTerminator] - Continue语句:继续[这里没有LineTerminator]标识符; BreakStatement:破[无LineTerminator这里]标识符; ReturnStatement:返回[这里没有LineTerminator]表达; ThrowStatement:这里没有LineTerminator]扔表达; 这些限制生产的实际效果是如下:当一个++或 - 令牌遇到其中解析器将其当作一个后缀运算符,和在前令牌和++或之间发生的至少一个LineTerminator - 令牌令牌 - 时,则分号++或之前被自动插入。 当继续休息,返回,或者抛出令牌遇到和LineTerminator是下一个记号以前也遇到过,一个分号自动继续,休息一下,回来后插入,或抛出令牌。 在ECMAScript程序员产生的实用的建议是:A ++后缀或 - 运营商应该出现在同一行作为其操作数。 在退货或throw语句的表达应该开始在同一行作为返回或抛出令牌。 在休息的标识符或continue语句应在同一行符或继续令牌。

自动分号插入的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语句返回一个值,因为LineTerminator从令牌返回其分离。 来源

a = b
++c

通过自动分号插入以下变换:

a = b;
++c;

注意令牌++因为LineTerminator B和++之间产生不被视为适用于变量b后缀运算符。 来源

if (a > b)
else c = d

是不是有效的ECMAScript句子,并通过自动插入分号前的其他标记没有改变,即使没有生产语法的应用在这一点上,因为在自动插入的分号将被解析为空语句。 来源

a = b + c
(d + e).print()

不被自动分号插入转化,因为开始的第二行的parenthesised表达可以被解释为对于函数调用中的参数列表:

a = b + c(d + e).print()

在赋值语句必须用左括号开始的情况下,它是程序员在前面语句的结束提供一个明确的分号,而不是依赖于自动分号插入一个好主意。



Answer 3:

您return语句会在所有浏览器正常工作,如克里斯托夫指出。 我不喜欢,使其更加明确的,如果没有电脑,但人类至少通过将和运营商是不同的:

return a &&
       b &&
       c;

在这种情况下,没有人需要花费如果自动分号打算肆虐第二疑惑。 我只喜欢这种对JavaScript,你原来的代码更容易阅读。



文章来源: Automatic semicolon insertion & return statements [duplicate]