Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript'的规则是什么;自动分号插入(ASI)?_Javascript_Automatic Semicolon Insertion - Fatal编程技术网

JavaScript'的规则是什么;自动分号插入(ASI)?

JavaScript'的规则是什么;自动分号插入(ASI)?,javascript,automatic-semicolon-insertion,Javascript,Automatic Semicolon Insertion,首先,我应该问一下这是否依赖于浏览器 我已经读到,如果发现一个无效的标记,但代码部分在该无效标记之前是有效的,那么如果标记前面有换行符,则在该标记之前插入一个分号 然而,对于分号插入引起的错误,最常见的例子是: return _a+b; $('#myButton') .click(function(){alert("Hello!")}); …这似乎不符合这个规则,因为_a是一个有效的代币 另一方面,断开呼叫链的工作与预期一样: return _a+b; $('#myButton

首先,我应该问一下这是否依赖于浏览器

我已经读到,如果发现一个无效的标记,但代码部分在该无效标记之前是有效的,那么如果标记前面有换行符,则在该标记之前插入一个分号

然而,对于分号插入引起的错误,最常见的例子是:

return
  _a+b;
$('#myButton')
  .click(function(){alert("Hello!")});
…这似乎不符合这个规则,因为_a是一个有效的代币

另一方面,断开呼叫链的工作与预期一样:

return
  _a+b;
$('#myButton')
  .click(function(){alert("Hello!")});

有人对这些规则有更深入的描述吗?

首先,您应该知道哪些语句受自动分号插入(为简洁起见,也称为ASI)的影响:

  • 空话
  • var
    语句
  • 表达式语句
  • do while
    语句
  • 继续
    语句
  • break
    语句
  • return
    语句
  • throw
    语句
ASI的具体规则见本规范

描述了三种情况:

  • 当遇到语法不允许的违规标记时,如果出现以下情况,将在其前面插入分号:
    • 至少有一个
      LineTerminator
      将令牌与上一个令牌分开
    • 令牌是
      }
    e、 g:

    转化为

        { 1
        ;2 ;} 3;
    
        return;
          "something";
    
    NumericLiteral
    1
    满足第一个条件,以下标记是行终止符。
    2
    满足第二个条件,以下标记为
    }

  • 当遇到令牌输入流的结尾,并且解析器无法将输入令牌流作为单个完整程序进行解析时,将自动在输入流的结尾插入分号
  • e、 g:

    转换为:

        a = b;
        ++c;
    
  • 当语法的某些产品允许标记,但该产品是受限产品时,会自动在受限标记之前插入分号,出现这种情况
  • 限制制作:

        UpdateExpression :
            LeftHandSideExpression [no LineTerminator here] ++
            LeftHandSideExpression [no LineTerminator here] --
        
        ContinueStatement :
            continue ;
            continue [no LineTerminator here] LabelIdentifier ;
        
        BreakStatement :
            break ;
            break [no LineTerminator here] LabelIdentifier ;
        
        ReturnStatement :
            return ;
            return [no LineTerminator here] Expression ;
        
        ThrowStatement :
            throw [no LineTerminator here] Expression ; 
    
        ArrowFunction :
            ArrowParameters [no LineTerminator here] => ConciseBody
    
        YieldExpression :
            yield [no LineTerminator here] * AssignmentExpression
            yield [no LineTerminator here] AssignmentExpression
    
    经典的例子是
    ReturnStatement

        return 
          "something";
    
    转化为

        { 1
        ;2 ;} 3;
    
        return;
          "something";
    
    直截了当地说:

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

  • 当从左到右解析程序时,遇到任何语法生成都不允许的标记(称为违规标记),如果满足以下一个或多个条件,则会自动在违规标记之前插入分号:
    • 至少有一个
      LineTerminator
      将有问题的令牌与前一个令牌分开
    • 有问题的标记是}
  • 当从左到右解析程序时,遇到令牌输入流的结尾,并且解析器无法将输入令牌流解析为单个完整的ECMAScript
    program
    ,则会自动在输入流的结尾插入分号
  • 当从左到右解析程序时,遇到语法的某些产品所允许的标记,但该产品是受限产品,并且该标记将是紧跟在注释“[no
    LineTerminator
    here]”之后的终端或非终端的第一个标记在受限生产内(因此此类令牌称为受限令牌),受限令牌与前一个令牌之间至少有一个行终止符,然后在受限令牌之前自动插入分号
  • 但是,上述规则还有一个附加的覆盖条件:如果分号将被解析为空语句,或者分号将成为for语句头中的两个分号之一,则不会自动插入分号(请参见12.6.3)


    关于分号插入和var语句,请注意在使用var但跨越多行时忘记逗号。昨天有人在我的代码中发现:

        var srcRecords = src.records
            srcIds = [];
    

    它运行了,但效果是srcIds声明/赋值是全局的,因为上一行带有var的局部声明不再应用,因为该语句由于自动插入分号而被视为已完成。

    我不能太好地理解规范中的这3条规则——希望有更简单的内容英语——但以下是我从JavaScript中收集到的信息:《权威指南》,第6版,大卫·弗拉纳根,O'Reilly,2011年:

    引述:

    JavaScript不会将每一个换行符都视为分号:只有当它无法解析没有分号的代码时,才会将换行符视为分号

    另一句话:代码

    var a
    a
    =
    3 console.log(a)
    
    JavaScript不会将第二个换行符视为分号,因为它可以继续解析较长的语句a=3

    以及:

    当JavaScript无法将第二行解析为第一行语句的延续时,它将换行符解释为分号的一般规则有两个例外。第一个异常涉及return、break和continue语句

    。。。如果这些单词后面出现换行符。。。JavaScript总是将该换行符解释为分号

    。。。第二个异常涉及++和−− 操作员。。。如果要将这些运算符中的任何一个用作后缀运算符,则它们必须与应用于它们的表达式显示在同一行。否则,换行符将被视为分号,并且++或-,将被解析为应用于后面代码的前缀运算符。考虑这个代码,例如:

    它被解析为
    x++y,而不是
    x++;y

    所以我瘦了
    return;   // returning nothing
    {
      foo: 1
    }
    
    return { 
      foo: 1
    }
    
    return { 
      foo: 1
    };
    
    const foo = function(){ return "foo" } //this doesn't add a semicolon here.
    (function (){
        console.log("aa");
    })()