2012-07-17 4 views
8

私はちょうどsource of JSLintを閲覧し、コードのこの部分に気づいた:グローバルコードでラベル付きステートメントを使用すると何が問題になりますか?

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

興味深い部分がfunct === global_funct比較です。あなたは、同じスニペットを配置する場合

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

:ラベル付きステートメントは、グローバル実行コンテキスト(。。私が知っている、それは愚かな例ですHere's a fiddle)であるため、JSLintを通じて次のスニペットを実行すると、「予期しないラベル」エラーがスローされます関数では、JSLintは完全に満足していて、ラベルに遭遇したときにエラーをスローしません。 Here's a fiddleにはJSLintを渡すコードが含まれています。試してみたい場合は、コードをonline version of JSLintに貼り付けることができます。

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

+0

「Gotoは有害だと思っています」というバリエーションのように思われます。 –

+0

これは最新のjavascriptではサポートされていないことを本当に願っています:https://developer.mozilla.org/ja/JavaScript/Reference/Statements/label – jbabey

+0

@RobertHarvey - 実際にはそうですが、なぜグローバルコードで動作が異なるのですか? –

答えて

3

ラベル付きステートメントの動作を調査したところ、実際には実際には根拠のないCrockfordの選択肢に過ぎないと思います。私が言う限りでは、グローバルスコープ内のラベルと命名の競合を引き起こす可能性のある状況はありません。なぜなら、JSLintがそれを許可しない理由について人々が考える主な理由であるように思われます。

ES5仕様状態section on labelled statementsに次

生産識別子:書のラベルセットに 識別子を添加した後、を評価することによって評価されます。

...

LabelledStatement、含まの評価には、それが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; 
} 

、あなたはラベル付きステートメントにラベルを付けることができます0

LabelledStatement自体に空でないラベルセットがある場合、これらのラベルは の評価前にステートメントのラベルセットにも追加されます。上記のスニペットで

for文のラベルセットは、2つのラベル(anotherlabel)が含まれています。 forステートメント内ののラベルのうちのいずれか1つをに分解することは可能です。

そして最後に、スペックも述べて(強調は追加):

ラベル付きステートメントは、唯一のラベルbreakcontinue文と一緒に使用されています。 ECMAScriptにはgotoがありません。

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

関連する問題