es3推出的try catch想必大家都不陌生,这是一个标准的捕获异常的方法。通常,遇到异常,浏览器会停止执行js并抛出异常。如果出现异常的代码在try catch内,浏览器不会中断js线程,而是会执行catch内的代码,触发catch函数并将异常作为参数传递给函数。
这篇文章暂且只讨论try catch创建的作用域,不专门介绍用法。try catch具体用法参考 try catch MDN
在es6的let和const推出之前,除了已经废弃的with,以及这里讨论的 try catch,js并没有块作用域的概念,只有全局作用域和函数作用域。
不过,catch创建的块作用域也不是通常的块作用域。
下面是个例子
function foo(){
e='aaa'
try{
throw new Error('this is an error')
}catch(e){
console.log(e)
}
console.log(e)
console.log(window.e)
}
foo()
结果是
在函数里面先默认声明了一个全局变量,变成了window的一个属性。
如果在catch里面声明一个变量e呢?
如果用var声明变量e,那么按照块作用域的特性,不会影响外部的变量e。然而,结果并不是这样
function foo(){
e='aaa'
try{
throw new Error('this is an error')
}catch(e){
var e;
console.log(e)
}
console.log(e)
console.log(window.e)
}
foo()
可以看到,外部的e='aaa'并没有给window绑定上e属性,对比上一次的代码,很容易就能得出结论:
catch里面对e的声明提升到了foo顶部。
所以,catch的作用域,其实并不是常见的块作用域,并不能绑定自己的内部声明的变量。
接下来,在catch内部更改e的值。
function foo(){
e='aaa'
try{
throw new Error('this is an error')
}catch(e){
var e;
console.log(e)
e='this is not an error';
console.log(e)
}
console.log(e)
console.log(window.e)
}
foo()
如下。catch内部的e已经更改了,不过外部的e还是原始值。这也说明catch的确创建了一个作用域,catch的作用域的内部变量e的值并没有影响到外部作用域的e的值。
再来试试对其他属性的影响
function foo(){
e='aaa'
a='a'
try{
throw new Error('this is an error')
}catch(e){
var e,a='b';
console.log(e)
e='this is not an error';
console.log(e)
}
console.log(e)
console.log(window.e)
console.log(a)
}
foo()
所以,catch的作用域并不能影响其他属性。
由此,可以推测出:
catch创建的块作用域,只对catch的参数有效。对于在内部声明的变量,catch并没有创建一个新的作用域,只是一个普通的代码块。