自动分号插入和返回语句[重复]

问题描述 投票:13回答:3

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

您可能知道,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语句之外还有其他内容,自动分号插入是否会“唤醒”?任何人都可以提供有关此实现级别的详细信息

javascript specifications ecmascript-5 automatic-semicolon-insertion
3个回答
12
投票

如果之后有有效的Javascript,javascript解释器/编译器非常聪明,只能插入自动分号。

你的代码是有效的,因为它所代表的&& b没有有效的表达式 - 这就是为什么在return a之后没有插入分号导致:

return a && b && c;

然而:

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

是完全有效的,这就是分号插入的原因。

为了完整性,参考规范的参考:automatic semicolon insertion。这些例子值得一读。


2
投票

不是浏览器/实现特定的,但qazxsw poi的qazxsw poi值得一读。

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] - ContinueStatement:continue [此处没有LineTerminator]标识符; BreakStatement:break [此处没有LineTerminator]标识符; ReturnStatement:return [no LineTerminator here] Expression; ThrowStatement:抛出[此处没有LineTerminator]表达式;这些限制产生的实际效果如下:当遇到++或 - 令牌时,解析器将其视为后缀运算符,并且在前一个令牌与++或 - 令牌之间至少发生一个LineTerminator ,然后在++或 - 标记之前自动插入分号。遇到continue,break,return或throw标记并且在下一个标记之前遇到LineTerminator时,会在continue,break,return或throw标记之后自动插入分号。由此产生的对ECMAScript程序员的实用建议是:后缀++或 - 运算符应与其操作数出现在同一行。 return或throw语句中的表达式应该与return或throw标记在同一行开始。 break或continue语句中的标识符应与break或continue标记位于同一行。

7.9.2自动分号插入的示例

来源

Section 7.9 Automatic Semicolon Insertion

即使使用自动分号插入规则,它也不是ECMAScript语法中的有效句子。相比之下,来源

ECMAScript Language Specification

也不是有效的ECMAScript句子,但通过自动分号插入转换为以下内容:

{ 1 2 } 3

这是一个有效的ECMAScript句子。来源

{ 1
2 } 3

不是有效的ECMAScript语句,并且不会被自动分号插入更改,因为for语句的标题需要分号。自动分号插入永远不会在for语句的标题中插入两个分号中的一个。来源

{ 1
;2 ;} 3;

通过自动分号插入转换为以下内容:

for (a; b
)

注意表达式a + b不被视为return语句返回的值,因为LineTerminator将它与令牌返回值分开。来源

return
a + b

通过自动分号插入转换为以下内容:

return;
a + b;

注意令牌++不被视为应用于变量b的后缀运算符,因为在B和++之间出现LineTerminator。来源

a = b
++c

不是有效的ECMAScript语句,并且在else标记之前不会被自动分号插入更改,即使此时没有生成语法,因为自动插入的分号将被解析为空语句。来源

a = b;
++c;

自动分号插入不会转换,因为从第二行开始的括号表达式可以解释为函数调用的参数列表:

if (a > b)
else c = d

在赋值语句必须以左括号开头的情况下,程序员最好在前一个语句的末尾提供一个显式分号,而不是依赖于自动分号插入。


0
投票

Christoph指出,您的return语句将在所有浏览器中正常运行。我更愿意让它变得更加明确,如果不是为了计算机而是为了人类,至少通过以不同的方式放置和运算符:

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

在这种情况下,没有人需要花费一秒钟,想知道自动分号是否会造成严重破坏。我只喜欢这个用于JavaScript,您的原始代码更易于阅读。

© www.soinside.com 2019 - 2024. All rights reserved.