2013-02-22 54 views
5

考虑以下摘录from ECMA-262 v5.1(我最近在this question看到的):为什么catch子句有他们自己的词汇环境?

甲词法环境是用于定义标识符基于的ECMAScript的代码的词法嵌套结构中的特定的变量和函数的相关联的规范类型。词法环境由一个环境记录和一个可能为空的外部词法环境引用组成。通常,词法环境与某些ECMAScript代码的特定语法结构相关联,例如FunctionDeclaration,WithStatement或TryStatement的Catch子句,并且每次评估此类代码时都会创建一个新的词法环境。

我认为这意味着类似的功能做的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

“可能为null的外部词法环境引用”。意味着它也可以不为null,当它不为null时,它会发现全局变量就好了。 – 2013-02-22 23:25:21

+0

@ Mike'Pomax'Kamermans我实际上期待'catch'可以拥有自己的局部变量,并且映射到全局变量。但它不能,因为为它创建的词法环境是另一种类型(参见Bergi的答案,以及[10.3]中的规范(http://www.ecma-international.org/ecma-262/5.1/#sec -10.3))。 – bfavaretto 2013-02-23 04:21:22

回答

5

是的,catch子句确实有它们自己的词汇环境。看看happens when it is evaluated:它创建一个新的(从当前派生的)并将异常标识符绑定到它。当执行catch块时,当前的Execution Context'sLexicalEnvironment被切换到新的,而VariableEnvironment(“其环境记录保存由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,其中块级函数声明有效并关闭块范围)

+0

现在你已经说过了,它总是有意义的,即异常对象需要单独的记录。当你说'VariableEnvironment'保持不变时,是因为规范没有说应该创建一个新规范,还是明确指出它应该保持不变? – bfavaretto 2013-02-23 02:18:39

+0

是的,它没有明确说明,但由于词法环境是执行环境的独特组件,我没有看到什么会改变变量环境 - 并且没有建立新的环境,只有当前的环境被修改(和块执行后复位)。 – Bergi 2013-02-23 03:55:25

+0

谢谢,现在很清楚。我了解到变量环境在同一个执行上下文中永远不会改变,所以我期望从catch获得的效果是不可能的。它发生在函数中,因为它们创建全新的执行上下文。 – bfavaretto 2013-02-23 04:13:50

相关问题