1. ホーム
  2. javascript

[解決済み] JavaScriptのセミコロン自動挿入(ASI)のルールとは?

2022-03-18 20:03:03

質問

さて、まず最初に、これはブラウザに依存するものなのかどうかを聞いておく必要がありそうです。

無効なトークンが見つかったが、その無効なトークンまではコードのセクションが有効である場合、そのトークンの前に改行がある場合はセミコロンが挿入されると読んだことがあるのですが、どうなのでしょうか?

しかし、セミコロン挿入によるバグの例としてよく引き合いに出されるのが

return
  _a+b;

...これはこのルールに従わないようです。なぜなら _a は有効なトークンだからです。

一方、コールチェーンの分割は期待通りに機能します。

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

どなたか、もっと詳しいルールの説明をお持ちの方はいらっしゃいませんか?

解決方法は?

まず最初に、どの文がセミコロンの自動挿入(簡略化してASIとも呼ばれる)の影響を受けるかを知っておく必要があります。

  • 空の文
  • var ステートメント
  • expression 文
  • do-while ステートメント
  • continue ステートメント
  • break ステートメント
  • return ステートメント
  • throw ステートメント

ASIの具体的なルールは、仕様書に記載されています。 §11.9.1 セミコロン自動挿入の規則

3つのケースを説明します。

  1. 文法上許されない違反トークンが発生した場合、その前にセミコロンが挿入される if:
  • そのトークンと前のトークンとの間に少なくとも1つの LineTerminator .
  • トークンは }

など :

    { 1
    2 } 3

は次のように変換されます。

    { 1
    ;2 ;} 3;

NumericLiteral 1 が最初の条件を満たしている場合、次のトークンは行末になります。
2 が2番目の条件を満たす場合、次のトークンは } .

  1. トークンの入力ストリームの終わりに遭遇し、パーサーが入力トークン・ストリームを単一の完全なプログラムとして解析できない場合、入力ストリームの終わりにセミコロンが自動的に挿入されます。

:

    a = b
    ++c

が変換されます。

    a = b;
    ++c;

  1. このケースは、あるトークンが文法の何らかのプロダクションで許可されているが、そのプロダクションが 制限付きプロダクション 制限されたトークンの前には、自動的にセミコロンが挿入されます。

制限されたプロダクションです。

    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";

は次のように変換されます。

    return;
      "something";