8

JSLintのソースを閲覧していて、次のコードに気付きました。

// Is this a labeled statement?
//...
if (next_token.labeled !== true || funct === global_funct) {
    stop('unexpected_label_a', label);
} //...

興味深い部分はfunct === global_funct比較です。JSLint を介して次のスニペットを実行すると、「予期しないラベル」エラーがスローされます。これは、ラベル付きステートメントがグローバル実行コンテキストにあるためです (私は知っていますが、これはばかげた例です。ここにフィドルがあります)。

loop:
for (var i = 0; i < 10; i++) {
    if (i === 5) {
        break loop;
    }
}

同じスニペットを関数に配置すると、JSLint は完全に満足し、ラベルに遭遇してもエラーをスローしません。これは、 JSLint を渡すコードのフィドルです。試してみたい場合は、コードを JSLintのオンライン バージョンに貼り付けることができます。

私の質問: グローバル コードでラベル付けされたステートメントを使用することに何か問題がありますか、それとも Crockford の別の個人的な選択ですか?

4

1 に答える 1

3

ラベル付けされたステートメントの動作を調査した結果、これは実際にはクロックフォードによる単なる選択であり、実際には実際の根拠はないと思います。私が知る限り、グローバルスコープでラベルとの命名の競合を引き起こす可能性のある状況はありません(そして、それがJSLintがそれを許可しない理由について人々が考えることができる主な理由であるように思われました-質問のコメントを参照してください)。

ES5 仕様では、ラベル付きステートメントのセクションに次のように記載されています。

プロダクションIdentifier : Statementは、 IdentifierをStatementのラベル セットに追加してから、 Statement を評価することによって評価さ ます。

...

LabelledStatementの評価の前に、含まれているStatementは、それがIterationStatementまたはSwitchStatementである場合を除き、空のラベル セットを所有していると見なされemptyます。

これは、すべてのステートメントにラベルが設定されていることを意味します。ラベル識別子は変数や関数の識別子から独立しているため、同じスコープ内の変数と同じ識別子を持つラベルを持つことは構文的に許容されます。つまり、これは有効です。

var label = "My Label";
label:
for (var x = 1; x < 10; x++) {
    break label;
}

各ステートメントには独自のラベル セットがあるため、これも有効です。

label:
for (var x = 1; x < 10; x++) {
    //Looks for 'label' in label set of `break` statement, then `for` statement
    break label;
}
label:
for (var y = 5; y < 15; y++) {
    //Same again. Will never look for label outside the enclosing `for` statement
    break label;
}

任意のステートメントにラベルを付けることができるため (無意味ですが、可能です)、ラベル付きステートメントにラベルを付けることができます。

another:
label:
for (var y = 5; y < 15; y++) {
    break label;
}

この場合、仕様には次のように記載されています。

LabelledStatement自体に空でないラベル セットがある場合、これらのラベルは、評価する前に Statement のラベル セットにも追加されます。

上記のスニペットでは、forステートメントのラベル セットに 2 つのラベル (anotherlabel) が含まれています。ステートメント内からこれらのラベルのいずれかにブレークすることができます。for

最後に、仕様にも次のように記載されています (強調を追加)。

ラベル付きステートメントは、ラベル付きbreak およびcontinueステートメントと組み合わせてのみ使用されます。ECMAScript にはgotoステートメントがありません。

そのため、グローバル コード内のラベルが他のグローバル コードに干渉する可能性があるとは考えられません。もちろん、同じ識別子を持つ複数のラベルを含むプログラムが必要になる可能性はほとんどなく、JSLint は既に「ラベルは既に定義されています」というエラーをスローすることでそれを防いでいます。しかし、グローバル実行コンテキストでラベル付きステートメントを処理する方法に違いはないと思います。

于 2012-07-18T09:14:44.610 に答える