let的暂时性死区
const与let在这个地方原理上差不多,故以let为例进行分析
1.什么是暂时性死区
首先来看一段代码
console.log(a); // undefined
var a = 123;
如果你了解变量提升,那么很容易就会知道,var 声明变量的这段代码相当于
var a
console.log(tmp); // undefined
a = 123;
但同样的代码用let声明变量时会报错
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 123;
这是因为忽视了 let 的 暂时性死区(上面代码中console.log(a)中的a就是在暂时性死区中)
ES6规定,let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。 总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。 这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)
大家常常记住的是let所声明的变量一定要在声明后使用就是这个原因
2.暂时性死区中区的‘范围’
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。 ES6 中let实际上为 JavaScript 新增了块级作用域。
再来以下看2段代码,理解let/const 命令会使区块形成封闭的作用域
var a = 123;
if (true) {
console.log(a); // 123
}
var a = 123;
if (true) {
console.log(a); // ReferenceError: Cannot access 'a' before initialization3
let a
}
在第2段代码中,使用了let,let/const 命令会使区块形成封闭的作用域,即
if (true) {
// let命令行成的封闭的作用域
}
故在if外面,用var声明的变量,会被let的作用域接管。 那么在这个作用域里什么地方是暂时性死区呢,其实很简单,在这个作用域里let声明变量之前的,都是这个变量的暂时性死区。
var a = 123;
if (true) {
// 变量a的暂时性死区开始
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a;
// 变量a的暂时性死区开始
console.log(a); // undefined
a = 123;
console.log(a); // 123
}
如图
3.暂时性死区带来的影响(使用let时需要注意的事项)
- let所声明的变量一定要在声明后使用,否则报错
- let不允许在相同作用域内,重复声明同一个变量
- typeof 不再是一个百分之百安全的操作
关于第三点,可看如下代码
typeof a // ReferenceError: Cannot access 'a' before initialization
let a