JavaScript catch子句作用域
JavaScript catch clause scope
ECMAScript 5规范声明如下:
通常词法环境与一些特定的ECMAScript代码的语法结构,如FunctionDeclaration,一个WithStatement,或者一个TryStatement的Catch子句和一个新的Lexical环境将在每次计算此类代码时创建。
如果我的理解是正确的,那么当在JavaScript中创建一个新的词法环境时,就会进入一个新的作用域,这就是为什么在函数内声明的变量在该函数外不可见的原因:
function example() {
var x = 10;
console.log(x); //10
}
console.log(x); //ReferenceError
因此,在上面的函数声明中,创建了一个新的词法环境,这意味着x
在任何可能存在的外部词法环境中都不可用。
所以上面引用的关于函数声明的部分似乎是有意义的。但是,它还声明为Try语句的Catch子句创建一个新的词法环境:
try {
console.log(y); //ReferenceError so we enter catch
}
catch(e) {
var x = 10;
console.log(x); //10
}
console.log(x); //10 - but why is x in scope?
那么catch
块的作用域是如何工作的?我对什么是词法环境有根本性的误解吗?
如果我理解正确的话,那么它的意思可能是,在你的代码中,
try {
console.log(y); //ReferenceError so we enter catch
}
catch(e) {
var x = 10;
console.log(x); //10
}
e
只存在于catch块中。在catch块之外尝试console.log(e);
,它将抛出ReferenceError。
与WithStatement一样,with ({x: 1, y: 2}) { }
、x和y只存在于with块中。
但这并不意味着var
声明将被绑定到最接近的词法环境。实际上,var
声明将在进入执行上下文时绑定到环境。
10.5声明绑定实例化:当进入执行上下文时,它会查找函数声明、参数和变量声明,然后在执行上下文的VariableEnvironment中创建绑定。
因此,使用var
声明的任何变量都可以在函数中的任何地方访问,无论控制结构如何,也无论它在函数中的定义位置如何。注意,这并不包括嵌套函数,因为它们是一个单独的执行上下文。
这意味着var
声明将被绑定到最近的执行上下文。
var x = 1;
(function() {
x = 5; console.log(x); // 5
if (false) { var x; }
x = 9; console.log(x); // 9
})();
console.log(x); // 1
所以在上面的代码中,x = 5;
将在内部函数中设置x
变量,因为if (false) { var x; }
中的var x;
在函数代码执行之前已经绑定到该函数。
From dev.opera
try-catch-finally构造是相当独特的。与其他构造不同,在运行时在当前作用域中创建一个新变量。每次执行catch子句时都会发生这种情况,其中捕获的异常对象被分配给一个变量。该变量不存在于脚本的其他部分中,即使在同一作用域中也是如此。它在catch子句开始时创建,然后在catch子句结束时销毁。
所以看起来唯一真正在catch范围内的是异常本身。其他操作似乎被(或保持)绑定到catch的外部作用域(在本例中是全局作用域)。
try {
console.log(y); //ReferenceError so we enter catch
}
catch(e) {
var x = 10;
console.log(x); //10
}
console.log(e.message); //=> reference error
在ES5中,这些行可能与以下内容相关(加粗/强调):
- 设oldEnv为正在运行的执行上下文的LexicalEnvironment。
- 让catchEnv是调用NewDeclarativeEnvironment传递的结果
在那部分的末尾也写着:
注意:无论控件如何离开Block LexicalEnvironment总是恢复到原来的状态
由于它在ES3中被标准化,catch () {}
子句(据我所知)是es2015之前唯一创建块级作用域的javascript结构,仅仅因为它是唯一的块级结构,带有参数。
这就是为什么它被用作polyfill被下一代javascript转译器编译的原因:
ES2015:
{ let priv = 1; }
console.log(priv); // throws ReferenceError
:
try { throw void 0 } catch (priv) { priv = 1 }
console.log(priv); // throws ReferenceError
我对这个问题感到困惑,因为我似乎已经遇到了类似的问题,与特定的catch块无关,而是在函数定义中。现在我才想起来,实际上我在几周前也写过关于这个问题的博客:)。
用下面的代码:
function test(){
var x = "Hi";
(function(){
console.log(x);
var x = "Hi, there!";
})();
}
代码:http://jsbin.com/alimuv/2/edit javascript,生活
输出是什么??通过快速查看它,人们可能会认为它是"Hi",因为变量x的作用域取自函数的外部作用域。相反,undefined
被打印出来。原因与catch块问题相同:词法作用域,这意味着作用域是在函数定义而不是在运行时创建的。
- 监视函数从服务返回不起作用,但作用域函数起作用
- 将作用域存储在JSON中
- 从控制器继承了隔离的作用域以生成可重用的指令
- 从ng模板访问作用域
- 调用私有作用域
- 对父作用域的指令更新延迟了一步
- 正在$rootScope上达到控制器作用域$在内部控制器上
- 两个指令创建新的继承的和隔离的作用域-元素得到哪个
- 这两个关于 JavaScript 作用域链的例子有什么区别?
- 在具有命名作用域的自定义Polymer元素中隐藏表行
- AngularJS指令隔离作用域
- Angularjs:修改js中的作用域,稍后在页面中使用
- 访问多个指令的隔离作用域
- Javascript作用域和Ajax调用;工作不正常
- 向Angular作用域对象添加对象数组——TypeError
- ng重复中的ng模型-初始化唯一作用域属性
- 在put方法之前从作用域获取数据
- 如何在html中以角度显示自定义指令的作用域
- 当提供函数名称时,检查函数是否存在于同一作用域中
- JavaScript catch子句作用域