JavaScript中分号自动插入

转译自:链接描述
在JavaScript中,分号自动插入机制允许在一行代码结尾省略分号。你应该养成一直书写分号的习惯,与此同时掌握JavaScript分号省略处理机制是十分重要的。因为这不仅有助于你去理解省略分号的代码,而且对于那些没有省略分号的代码也能有更深层次的理解。

背景:JavaScript语法

首先,我要介绍一些和本文剩余部分相关的语法现象,方便大家理解。

表达式VS语句

表达式:经计算后会有一个值。

 3 * Math.sqrt(x)
    i++
    obj.prop
    [ "a", "b", "c" ]
    { first: "Jane", last: "Doe" }
    function() {} // function expression

语句:程序是由一系列语句组成。

for(var i=0; i<3; i++) {
        console.log(i);
    }
    function twice(x) { // function declaration
        return 2 * x;
    }
    var foo = twice(21); // assignment

注意,赋值语句右边是一个表达式。
语句应该以分号结尾:在JavaScript中,任何语句都应该以分号结尾,但下面这些例外。、

  1. 循环语句:for,while(不是do while)

  2. 分支语句:if,switch,try

  3. 函数声明(不是函数表达式)
    示例1:while VS do while

while(a > 0) {
        a--;
    } // no semicolon
    
    do {
        a--;
    } while(a > 0);

示例2:函数声明 VS 函数表达式

 function foo() {
    } // no semicolon
    
    var foo = function() {
    };

注意,当你在上述提及到的语句后面加了分号,浏览器不会提示你有语法错误,因为它被视作为一个空语句。

空语句。当一个分号单独出现的时候,它代表一个空语句,什么也不会做。空语句可以出现在任何语句可以出现的地方。当一个语句是被需要的,但是又不需要这个语句完成什么功能的时候,空语句是非常有用的。在这种情况下,块代码也是允许的,不过一个空语句块要比一个分号要长。举个例子,西面两个语句是等价的:

 while(processNextItem() > 0);
 while(processNextItem() > 0) {}

下面的程序在语法上也是正确的:三个空语句。

;;;

表达式作为语句任何表达式都可以转换为语句,只需在表达式结尾加一个分号就可以了。比如:

 "hello world";
    a + b;
    sum(5, 3);
    a++;

分号自动插入规则(ASI)

分号插入只是一个术语。它并不意味着代码在解析的时候就真的被插入了分号。
相反,它只是一个很好的 用来解释当分号可有可无的情况下的 比喻说法。
规范:解析器把每一个新的记号当做当前语句的一部分,除非有一个分号来结束它。下面给出的示例代码,你也许会以为一个分号应该被插入,但实际上没有。下面例子阐明了忽略分号的危险。

NO ASI:

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

上述代码不会触发ASI,因为左括号可以跟在C后面作为函数调用。因此,上述代码被解释为:

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

NO ASI:

 a = b
    /hi/g.exec(c).map(d);

没有分号插入,第二条语句不会被解释为正则表达式。上述代码等价于:

a = b / hi / g.exec(c).map(d);   

NO ASI:

 var foo = "bar"
    [ "red", "green" ].foreach(function(c) { console.log(c) })

没有分号被插入。相反,第二行代码开头被解释为字符串“bar”的下标索引。由于逗号运算符的存在,方括号的逗号能够被解释器解释。
NO ASI:
在很多浏览器中,下面的代码中的func被赋值为0,因为a++被解释为上一行的函数表达式的参数。

 var a = 0;
    var func = function(x) { return x }
    (a++)

规范的例外:在下面的例子中ASI机制被应用。
换行加上非法的记号符:如果遇到了换行,并且接下来一行的代码被添加在上面代码中不能组成合法的语句,此时分号会被插入。
举个例子:

    if (a < 0) a = 0
    console.log(a)

上述代码会触发ASI机制,被解释为下面的语句:

if (a < 0) a = 0;
console.log(a);

禁止的行结束符:下面的句法结构中在特定位置禁止换行。如果在这些位置遇到换行了,分号将被插入。在ECMAScript标准中称下述语法规则为限制生产( 英文为restricted productions,暂且直译)。


Zuckjet
437 声望657 粉丝

学如逆水行舟,不进则退。