暂时性死区
暂时性死区简介
我们都知道,ES6增加了使用let和const声明的块级作用域。块级作用域虽然使很多操作更加方便了,但是同时也带来了新的概念,那就是“暂时性死区”(也叫“临时性死区”)。说到暫时性死区,还得从“变量提升”这个概念说起,我们先来看一个例子。
示例 使用var声明变量
function fn() {
console.log(n)
var n = 2077
}
fn()
>>> undefined
分析
之所以输出undefined,是因为变量n在函数内进行了提升。这个例子其实等价于下面的代码。
function fn() {
var n
console.log(n)
n = 2077
}
fn()
这里,我们是使用var来声明变量的。那么假如使用let或const来声明变量,结果又会是怎样的呢?
示例:使用let声明变量
function fn() {
console.log(n)
let n = 2077
}
fn()
>>> Uncaught ReferenceError ReferenceError: Cannot access 'n' before initialization
分析
这里之所以会报错,是因为使用let或const声明变量时,会形成个包含这个变量的封闭的块级作用域。在这个块级作用域中,如果在声明变量前访问该变量,程序就会报错。也就是说,只有在声明变量后,我们才能够访问到它的值。
在"{}"括起来的块级作用域中,存在着这样的一个“死区”,它开始于函数的开头,终止于变量声明所在的那一行,如图2-3所示。在这个区域内,我们是无法访问let或const声明的变量的。这个“死区”被称为“暂时性死区”。

深入了解暂时性死区
我们要特别注意一点:ES5是没有暂时性死区这种说法的,暂时性死区是随着ES6中let和const的引入而引入的。
示例
console.log(a)
let a = 2077
>>> Uncaught ReferenceError ReferenceError: Cannot access 'a' before initialization
分析
正常情况下,运行上面这段代码是会报错的。但是很多初学者运行的是使用Babel编译后的代码,发现浏览器并没有报错,而是输出了一个undefined。这是为什么呢?不是说这里存在暂时性死区吗?原因是,Babel会将ES6的let和const转换为ES5的var,此时上面的代码就会转化成下面这样。
'use strict'
{
console.log(a)
var a = 2077
}
>>> undefined
我们都知道,ES5的var不会造成暂时性死区,而是会发生变量提升,所以才会输出undefined。这里顺便说一下,要将ES6的代码转换为ES5的代码,我们可以借助Babel官方的在线工具。
示例
let a = 2077
{
console.log(a)
}
>>> 2077
分析
这个例子中的代码是不存在暂时性死区的,console会沿着作用域链往上寻找。对于暂时性死区,我们应该牢记:ES6之前是没有暂时性死区这种说法的,暂时性死区是随着ES6中let和const的引入而引入的。
