美文网首页
JavaScript自动分号补齐的坑

JavaScript自动分号补齐的坑

作者: clear灬 | 来源:发表于2017-03-08 16:16 被阅读0次

    自动分号补齐(auto semicolon insertion,简称ASI)

    在JavaScript中,行尾的分号有一种自动插入机制,如果新起了一行,并且这新的一行不能追加到当前语句时,会自动追加一个分号。但如果不加区分在每个表达式(Expression)和语句(statement)之后都手动输入分号,那么其中绝大部分的分号是无用的。

    导致上下文解析出错时需要分号

    会造成此类问题的token有6个:括号,方括号,正则开头的斜杠,加号,减号,字符串模板的反引号。当以这6个字符作为一行开头时,不会在上一行自动补全分号,造成解析出错。

    a = b
    (c + d).toString()
    

    会被解析成

    a = b(c + d).toString()
    

    即()会被看做是在调用函数b,和本意不符。所以应尽量避免以这6个字符作为一行的开头,如果避免不了,可以选择在行首加分号。

    绝对禁止的行结束符(restricted productions)

    如果在不该换行的地方换行了,就会自动插入一个分号。

    后缀表达式
       左值表达式 [无行终结符] ++
       左值表达式 [无行终结符] --
    Continue 语句
       continue [无行终结符] 标识符? ;
    Break 语句
       break [无行终结符] 标识符? ;
    Return 语句
       return [无行终结符] 表达式? ;
    Throw 语句
       throw [无行终结符] 表达式? ;
    

    [无行终结符] 代表此处禁止换行。对于后缀表达式,遵循的原则是避免修改上一行的值。 对于 continue, break, return 和 throw,遵循的原则是:如果他们不带参数,他们不会指向下一行(会被插入一个分号)。

    a
    ++
    b
    

    会被解析成

    a;
    ++b
    

    关于return 和 throw

    function test() {
     return
     3
    }
    test()
    

    输出的结果实际是 undefined,因为上述代码被解析成

    function test() {
     return;
     3
    }
    test()
    

    关于break 和 continue

    var num = 0
    outermost: 
    for(let i = 0, j; i < 100; i++) {
     for(j = 0; j < 100; j++) {
       if(i === 50 && j===50 ) {
         break
         outermost
       }
       num++
     }
    }
    console.log(num)
    

    此时break 和label标示符之间有一个换行符,此时会在break后自动补分号,outermost未起作用,输出的结果为95。当break 和 label标示符放在同一行即 break outermost时,输出结果为55。

    因此笔者建议要有良好的编码习惯,弄清ASI的规则,分号只加在必要的地方即可。

    参考文章

    尤雨溪在知乎的回答
    JavaScript 中的自动分号插入(ASI) : 迷渡

    相关文章

      网友评论

          本文标题:JavaScript自动分号补齐的坑

          本文链接:https://www.haomeiwen.com/subject/vlhbgttx.html