553

さて、最初に私はおそらくこれがブラウザに依存しているかどうかを尋ねるべきです。

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

ただし、セミコロンの挿入によって引き起こされるバグについて引用される一般的な例は次のとおりです。

return
  _a+b;

.. _aは有効なトークンであるため、このルールには従わないようです。

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

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

誰かがルールのより詳細な説明を持っていますか?

4

6 に答える 6

552

まず最初に、自動セミコロン挿入(簡潔にするためにASIとも呼ばれます)の影響を受けるステートメントを知っておく必要があります。

  • 空のステートメント
  • var声明
  • 式ステートメント
  • do-while声明
  • continue声明
  • break声明
  • return声明
  • throw声明

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

3つのケースについて説明します。

  1. 文法で許可されていない問題のあるトークンが検出されると、次の場合にセミコロンがその前に挿入されます。
  • トークンは、前のトークンから少なくとも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";
于 2010-05-17T02:12:19.350 に答える
59

仕様のこれらの3つのルールをあまりよく理解できませんでした-よりわかりやすい英語のものが欲しいです-しかし、JavaScriptから収集したものは次のとおりです:The Definitive Guide、第6版、David Flanagan、O'Reilly、2011年:

引用:

JavaScriptは、すべての改行をセミコロンとして扱うわけではありません。通常、JavaScriptは、セミコロンなしでコードを解析できない場合にのみ、改行をセミコロンとして扱います。

別の引用:コードについて

var a
a
=
3 console.log(a)

JavaScriptは、長いステートメントa = 3の解析を続行できるため、2番目の改行をセミコロンとして扱いません。

と:

JavaScriptが2行目を最初の行のステートメントの続きとして解析できない場合に、改行をセミコロンとして解釈するという一般的な規則の2つの例外。最初の例外には、return、break、およびcontinueステートメントが含まれます

...これらの単語のいずれかの後に改行が表示された場合...JavaScriptは常にその改行をセミコロンとして解釈します。

... 2番目の例外には++および---演算子が含まれます...これらの演算子のいずれかを接尾辞演算子として使用する場合は、適用する式と同じ行に表示する必要があります。それ以外の場合、改行はセミコロンとして扱われ、++または-は後続のコードに適用されるプレフィックス演算子として解析されます。たとえば、次のコードについて考えてみます。

x 
++ 
y

x; ++y;としてではなく、として解析されますx++; y

だから私はそれを単純化すると思います、それは意味します:

一般に、JavaScriptは、意味がある限り、コードの継続として扱います。ただし、次の2つの場合を除きます。(1)、、、、、および(2)のようなキーワードの後、returnまたは新しい行にある場合は、前の行の終わりにあります。breakcontinue++--;

「意味のある限りコードの続きとして扱う」という部分は、正規表現の貪欲なマッチングのように感じさせます。

上記のように、つまりreturn改行を使用すると、JavaScriptインタープリターは;

(再度引用:これらの単語のいずれかの後に改行が表示された場合[などreturn] ... JavaScriptは常にその改行をセミコロンとして解釈します)

そしてこの理由のために、の古典的な例

return
{ 
  foo: 1
}

JavaScriptインタープリターはそれを次のように扱うため、期待どおりに機能しません。

return;   // returning nothing
{
  foo: 1
}

return:の直後に改行があってはなりません。

return { 
  foo: 1
}

それが正しく機能するために。また、 afterステートメント;を使用する規則に従う場合は、自分自身を挿入できます。;

return { 
  foo: 1
};
于 2016-01-27T15:56:25.607 に答える
49

ECMA-262、第5版ECMAScript仕様から直接:

7.9.1自動セミコロン挿入の規則

セミコロンの挿入には、次の3つの基本的なルールがあります。

  1. プログラムが左から右に解析されるときに、文法の生成で許可されていないトークン(問題のあるトークンと呼ばれる)が検出された場合、次の1つ以上の場合、問題のあるトークンの前にセミコロンが自動的に挿入されます。条件は真です:
    • 問題のあるトークンは、前のトークンから少なくとも1つ離れていますLineTerminator
    • 問題のあるトークンは}です。
  2. プログラムが左から右に解析されるときに、トークンの入力ストリームの終わりに遭遇し、パーサーが入力トークンストリームを単一の完全なECMAScriptとして解析できないProgram場合、セミコロンが自動的に最後に挿入されます。入力ストリーム。
  3. プログラムが左から右に解析されるときに、文法の一部の生成で許可されるトークンが検出されたが、生成は制限された生成であり、そのトークンは、注釈の直後の終端記号または非終端記号の最初のトークンになります。制限付きプロダクション内の「[LineTerminatorここではありません]」(したがって、このようなトークンは制限付きトークンと呼ばれます)。制限付きトークンは、少なくとも1つのLineTerminatorによって前のトークンから分離され、制限付きトークンの前にセミコロンが自動的に挿入されます。

ただし、前述のルールには追加のオーバーライド条件があります。セミコロンが空のステートメントとして解析される場合、またはそのセミコロンがステートメントのヘッダーにある2つのセミコロンの1つになる場合、セミコロンが自動的に挿入されることはありませんfor(12.6を参照) 。 .3)。

于 2010-05-17T02:36:30.510 に答える
18

セミコロンの挿入とvarステートメントに関しては、varを使用しているが複数行にまたがっている場合は、コンマを忘れないように注意してください。誰かが昨日私のコードでこれを見つけました:

    var srcRecords = src.records
        srcIds = [];

実行されましたが、前の行のvarを使用したローカル宣言は、セミコロンの自動挿入によりステートメントが終了したと見なされたため適用されなくなったため、srcIds宣言/代入はグローバルでした。

于 2011-10-19T12:15:35.860 に答える
8

私が見つけたJavaScriptの自動セミコロン挿入の最も文脈的な説明は、 CraftingInterpretersに関する本から来ています。

JavaScriptの「自動セミコロン挿入」ルールは奇妙なものです。他の言語では、ほとんどの改行が意味があると想定しており、複数行のステートメントで無視する必要があるのはごくわずかですが、JSはその逆を想定しています。解析エラーが発生しない限り、すべての改行が無意味な空白として扱われます。含まれている場合は、元に戻り、前の改行をセミコロンに変換して、文法的に有効なものを取得しようとします。

彼はあなたが匂いをコード化するのと同じようにそれを説明し続けます。

このデザインノートは、それがどのように機能するかについて完全に詳細に説明すると、デザインダイアトリブになります。それは、悪い考えであるさまざまな方法すべてではありません。それは混乱です。JavaScriptは私が知っている唯一の言語であり、多くのスタイルガイドは、理論的にはそれらを削除することができますが、すべてのステートメントの後に明示的なセミコロンを要求します。

于 2019-07-16T01:29:36.333 に答える
3

追加するだけで、

const foo = function(){ return "foo" } //this doesn't add a semicolon here.
(function (){
    console.log("aa");
})()

即時呼び出し関数式(IIFE)を使用してこれを参照してください

于 2019-12-06T06:51:03.057 に答える