2013-02-22 11 views
5

は(私は最近this questionで見た)次の抜粋from ECMA-262 v5.1検討:なぜキャッチ句に独自のレキシカル環境があるのですか?

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

私は、関数が行うようcatch節のボディは独自の変数をホイストう意味と思ったが、どうやらthat's not the case

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

誰もがなぜ知っていますか?また、catch句にはそれ自身のレキシカル環境が必要なのはなぜですか?

+0

"可能であれば外部の語彙環境への参照。"ヌルでなくてもいいことを意味し、ヌルでない場合は、グローバル変数がうまく見つかるでしょう。 –

+0

@ Mike'Pomax'Kamermans私は、実際には、「キャッチ」にグローバル変数をシャドーイングする独自のローカル変数があると予想していました。しかし、そのために作成されたレキシカル環境は別のタイプのものです(Bergiの答えと[10.3]の仕様を参照してください(http://www.ecma-international.org/ecma-262/5.1/#sec -10.3))。 – bfavaretto

答えて

5

はい、実際にはcatch節には独自のレキシカル環境があります。 happens when it is evaluated:新しいもの(現在のものから派生したもの)を作成し、それに例外識別子をバインドします。 catchブロックを実行すると、(VariableStatementsFunctionDeclarationsで作成されたバインドを保持する環境レコードを持つ)は変更されずに、現在のExecution Context'sLexicalEnvironmentが新しいものに切り替わります。

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、ではもはや真実ではありませんブロックレベルの関数宣言は有効であり、ブロックスコープで閉じる)

+0

これで、例外オブジェクトに対して別のレコードが必要であるということが完全に理解できました。 'VariableEnvironment'が同じままであると言うとき、それは仕様が新しいものが作成されるべきであると言っていないか、あるいはそれが同じままであるべきであることが明示的に述べられているからですか? – bfavaretto

+0

ええ、明示的には述べられていませんが、レキシカル環境は実行コンテキストの別個のコンポーネントなので、私は変数環境を変更するものは見当たりません - 新しいコンテキストが確立されていないので、ブロック実行後にリセットされます)。 – Bergi

+0

ありがとうございます、今はっきりしています。変数環境が同じ実行コンテキスト内で決して変化しないことを知ったので、私が「キャッチ」から期待していた効果は不可能です。新しい実行コンテキストを作成するため、関数内で発生します。 – bfavaretto

関連する問題