![现代JavaScript编程:经典范例与实践技巧](https://wfqqreader-1252317822.image.myqcloud.com/cover/657/26793657/b_26793657.jpg)
2-4 块级作用域
ES6标准中的块级作用域实际上是由let与const关键字决定的。在ES6标准中新引入了let和const关键字,其用法与var关键字十分类似,都是进行变量的声明。不同的是,var声明的变量会存在变量泄露和变量提升,从而成为全局变量的问题。而let和const声明的变量则只在其所在的代码块中有效。所谓代码块,即由大括号包裹起来的区域,其可以是一些常用的语法结构,如分支结构、循环结构等,也可以是开发者自行创建的区域。示例如下:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P33_67006.jpg?sign=1739292009-zy3SXzRbmC9SAKpm5Ve7Wx2KKhTGHs8X-0-7ded161edbd4c2e06cebbffafc8b53d0)
上面的代码当程序运行到console.log(b)时会抛出异常。也就是说,使用let命令声明的变量,一旦脱离其所在的代码块,这个变量就不能再被使用。这种局部变量十分适合用于for循环结构,例如:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P34_69015.jpg?sign=1739292009-NcDrK4wXT4kPY56uktQL1pefuKDrCZmq-0-bd0ac05021b909e44755891eca171162)
let命令还有一个规则,其不存在变量提升,即在变量声明之前,此变量是不可使用的,而不是undefined,例如:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P34_69016.jpg?sign=1739292009-mylZL9zDNu3ySSFk4g46MgaMjibFmhDR-0-f36c47a7e776908060f840710f8c8d73)
使用let声明的变量也不可以进行重复声明,如下的写法也会抛出异常:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P34_69017.jpg?sign=1739292009-CgE1Q5ZQ80Nf1udXLugTR5avFY6moAac-0-c65516f0af7d5d764fb2ae7d47b585f3)
关于块级作用域还有一个特点需要特别注意,如果在块级作用域内使用let或const声明了某个变量,那么此作用域会形成对此变量的屏蔽。也就是说,即便外层作用域中也有同名的变量,也会被屏蔽掉,这种语法特性被称为暂时性死区,示例如下:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P34_67156.jpg?sign=1739292009-s6dg9VBd1mU8ccX5BQHHujda7lqkkS4o-0-5fef730341a9eb53486174c1cb3c584b)
上面的示例代码说明,在块级作用域中使用let声明了变量,那么在声明之前,这个变量都不能使用(尽管全局中也定义了同名的变量)。
我们回过头再来理解一下块级作用域。在ES5标准中是没有块级作用域这个概念的,我们在编写代码时,很容易产生内层变量覆盖外层变量和局部变量泄露为全局变量的问题。块级作用域使作用域内的变量不受外界影响,同时也不会影响外界,提高了代码的安全性。同时,块级作用域也是可以嵌套的,外层作用域无法读取内层作用域的变量,示例如下:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P34_67158.jpg?sign=1739292009-Zhs2pogCMu7oJeuIHnkJzqRtJd2RsY99-0-0fc7158d52298038ac7f0f0845f70594)
对于函数的声明,在ES6中也是遵守块级作用域规则的,在作用域内声明的函数只能在作用域内使用,例如:
![](https://epubservercos.yuewen.com/534FF6/15253386804113806/epubprivate/OEBPS/Images/Figure-P35_67160.jpg?sign=1739292009-LW6VUpCDYcgVZ8i0rdKOuPsKu5fG733x-0-5ba7842a7384010bc23d350b19682c88)