为了账号安全,请及时绑定邮箱和手机立即绑定

自动分号插入和返回语句

/ 猿问

自动分号插入和返回语句

PIPIONE 2019-10-23 12:37:44

如您所知,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?任何人都可以提供有关实现的详细信息吗?


查看完整描述

3 回答

?
当年话下

javascript解释器/编译器非常聪明,仅在之后有有效的Javascript时才插入自动分号。


您的代码可以正常工作,因为&& b它本身没有有效的表达式-这就是为什么在return a生成以下结果后不插入分号的原因:


return a && b && c;

然而:


return (undefined);//implicitely inserted

{

    ....

}

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


为了完整起见,请参考规范:自动分号插入。这些例子值得一读。


查看完整回答
反对 回复 2019-10-23
?
胡说叔叔

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


7.9自动分号插入


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


7.9.1自动分号插入规则分号插入有三个基本规则:


当从左到右解析程序时,遇到任何语法产生都不允许的令牌(称为冒犯令牌)时,如果以下一项或多项操作,则在冒犯令牌之前会自动插入分号条件为真:


至少有一个LineTerminator将有问题的令牌与前一个令牌分开。

令人讨厌的令牌是}。

当从左向右解析程序时,遇到令牌输入流的末尾,并且解析器无法将输入令牌流作为单个完整的ECMAScript程序进行解析,则分号将自动插入到末尾。输入流。


当从左向右解析程序时,遇到某种语法的某种生产所允许的令牌,但是该生产是受限制的生产,并且该令牌将成为紧随注解之后的终端或非终端的第一个令牌?[这里没有LineTerminator]?在受限生产中(因此此类令牌称为受限令牌),并且受限令牌通过至少一个LineTerminator与前一个令牌分开,然后在受限令牌之前自动插入分号。但是,上述规则还有一个额外的优先条件:如果分号随后将被解析为空语句,或者该分号成为for语句的标头中的两个分号之一,则永远不会自动插入分号。 12.6.3)。注意:以下是语法中仅有的限制形式:PostfixExpression:LeftHandSideExpression [此处没有LineTerminator] ++ LeftHandSideExpression [此处没有LineTerminator] – ContinueStatement:继续[此处没有LineTerminator]标识符;BreakStatement:break [这里没有LineTerminator]标识符;ReturnStatement:返回[此处没有LineTerminator]表达式;ThrowStatement:throw [此处没有LineTerminator]表达式;这些受限生产的实际效果如下:当遇到++或-令牌时,解析器将其视为后缀运算符,并且在前面的令牌和++或-令牌之间至少发生了LineTerminator ,然后会在++或-标记之前自动插入分号。当继续,休息,返回,在遇到下一个令牌之前遇到了“生成”或“抛出”令牌,并且在遇到LineTerminator时,在“继续”,“中断”,“返回”或“抛出”令牌之后自动插入了分号。由此给ECMAScript程序员带来的实用建议是:后缀++或-运算符应与其操作数出现在同一行。return或throw语句中的Expression应该与return或throw标记在同一行开始。break或continue语句中的标识符应与break或continue令牌位于同一行。return或throw语句中的Expression应该与return或throw标记在同一行开始。break或continue语句中的标识符应与break或continue令牌位于同一行。return或throw语句中的Expression应该与return或throw标记在同一行开始。break或continue语句中的标识符应与break或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;

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


if (a > b)

else c = d

不是有效的ECMAScript句子,并且不会在else标记之前通过自动分号插入来更改,即使此时不应用语法,因为这样一来,自动插入的分号将被解析为空语句。来源


a = b + c

(d + e).print()

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


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

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


查看完整回答
反对 回复 2019-10-23
?
侃侃尔雅

正如Christoph指出的那样,您的return语句将在所有浏览器中正常工作。我确实更希望使它更加明确,即使不是对于计算机而是对人类而言,至少要通过将和运算符不同地放置:


return a &&

       b &&

       c;

在这种情况下,没有人需要再三思考自动分号是否会造成严重破坏。我只喜欢JavaScript,您的原始代码更容易阅读。


查看完整回答
反对 回复 2019-10-23

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信