6

ECMA-262 v5.1 からの次の抜粋を検討してください(最近この質問で見ました)。

レキシカル環境は、ECMAScript コードのレキシカル ネスト構造に基づいて、識別子と特定の変数および関数との関連付けを定義するために使用される仕様タイプです。レキシカル環境は、環境レコードと、場合によっては外部レキシカル環境への null 参照で構成されます。通常、レキシカル環境は、FunctionDeclaration、WithStatement、または TryStatement の Catch 句などの ECMAScript コードの特定の構文構造に関連付けられており、そのようなコードが評価されるたびに新しいレキシカル環境が作成されます。

catchこれは、節の本体が関数のように独自の変数を巻き上げることを意味すると思っていましたが、明らかにそうではありません

var a = 1;
try {
    console.log(x); // ReferenceError
} catch(ex) {
    console.log(a); // 1, not undefined
    var a = 3;
}

理由を知っている人はいますか?catchまた、節が独自の語彙環境を必要とするのはなぜですか?

4

1 に答える 1

9

はい、catch節には確かに独自のレキシカル環境があります。評価されたときに何が起こるかを確認してください。新しいものを作成し(現在のものから派生)、例外識別子をそれにバインドします。catch ブロックを実行すると、現在の実行コンテキスト LexicalEnvironmentが新しいものに切り替えられますが、VariableEnvironment("その環境レコードはand "によって作成されたバインディングを保持しますVariableStatementsFunctionDeclarations) は変更されません。

console.log(a); // undefined - declared from within the catch,
                // but in the current VariableEnvironment
a = 1;
console.log(typeof ex); // undefined - no binding
try {
    console.log(ex); // a ReferenceError in this LexicalEnvironment
} catch (ex) { // introducing the new LexicalEnvironment
    console.log(ex); // …and it works here!
    var a = 3; // variable declaration
}

興味深い事実:句の中で関数を宣言catchしようとすると(ブロック内では構文的に無効ですが、「関数宣言ステートメント」は受け入れられることがよくあります)、そのスコープは現在のものになるVariableEnvironmentため、例外にアクセスできなくなります。

try {throw "some"} catch(x) { function y(){console.log(x, typeof x);} y(); }
                    // throws a ReferenceError for x   ^

(更新: これは ES6 では当てはまりません。ES6 では、ブロック レベルの関数宣言が有効であり、ブロック スコープを閉じます)

于 2013-02-22T23:38:17.283 に答える