0

ご存知かもしれませんが、JavaScript の厳密モードでは、識別子eval、 およびに制限が追加されarguments、実質的に予約語になりますが、次の 2 つの例外があります。

  • それらはまだ式として使用できます。つまり、式が期待される場所で使用できます (ただし、いくつかの例外があります)。
  • これらは引き続きラベル名として使用でき、break/continueステートメントでラベルを参照するために使用できます。

これで、最初の箇条書きがわかりました。たとえば、識別子が式として許可されていない場合 (および真の予約語が許可されていない場合)、関数をまったくeval呼び出すことができません( is は式であるため)。同じことが言えます-要素にアクセスできるようにするために、式として使用できる必要があります(例:)。evaleval(str)argumentsarguments[0]

ただし、この規則には 3 つの例外があります。eval/argumentsは、(1) 代入の左辺の式として (例: eval = true;)、(2) ++/のオペランドとして--(例: eval++)、(3) (delete例: ) のオペランドとして現れない場合がありますdelete eval。ただし、これらは唯一の例外であり、他のすべての式コンテキストでは有効です。

私が理解していないのは、2番目の箇条書きです。なぜ今でもラベル名として使用できるのですか? たとえば、次のコードは厳密モードでも有効です。

eval: for ( var i = 0; i < 10; i++ ) {
    arguments: for ( var j = 0; j < 10; j++ ) {
        if ( i < j ) continue eval;
        console.log( i - j );    
    }        
}

continue eval;がラベルを参照する方法であり、実際の機能evalとは何の関係もないことに注意してください。eval

また、真の予約語はラベル名として使用できないことに注意してください。私の理解では、厳密モードの意図は、名前evalを 、およびarguments可能な限り予約語のようにすることでした。それでは、なぜそれらを有効なラベル名として保持するのでしょうか?

4

1 に答える 1

1

理由はわかりませんが、かなり良い推測をすることができます。

evalおよびargumentsが変数名に対して制限されている (さらに言えば、禁止されている) 理由はwith、変数名がバインドされる場所 (つまり、ローカル変数、外側のスコープ内の変数、またはグローバル オブジェクトのプロパティ) に影響するためです。 1つ存在します)。これらの制限がなければ、一部の名前は実行時までバインドされず、すべての危険が伴います。

ラベル名は、変数名やプロパティ名などとは異なる名前空間を占有します。ラベルは静的に割り当てられ、ラベルの参照は静的に解決されるため、 break/のターゲットが曖昧になることはありません。continue(はい、evalコードにはラベルを含めることができます。ただし、evalラベルの解決はコンパイル時に行われ、ECMAScript ターミナルの呼び出しを含むスクリプトevalはプログラムであり、呼び出しによって実行されるコードevalはプログラムですが、この 2 つはラベル ターゲティングの目的で完全に分離されています。)

変数名を禁止する理由はevalarguments単にラベルには当てはまりません。したがって、ラベルには引き続き名前を付けることができますevalまたはarguments. ラベルにそのような名前を付けるのはばかげているでしょう。また、誰かが再び ECMAScript/JavaScript を設計した場合、それらはキーワードになり、ラベル名として使用できなくなります。しかし、それらをラベル名として禁止しても何の利益もありませんし、少なくともそれらを禁止しないための小さな互換性論争があるので、それらは禁止されませんでした。

于 2012-09-25T17:22:55.680 に答える