块级作用域诞生
在ES6之前,通过var关键字声明变量
js
if(false){
var value = 100;
}
console.log(value)
初学者可能会觉得条件为false,value不可能被创建,结果应该是报错,然而因为变量提升的原因,代码相当于:
js
var value;
if(false){
value = 100;
}
console.log(value); // undefined
除此之外,在 for 循环中:
js
for (var i = 0; i < 10; i++) {
...
}
console.log(i); // 10
即便循环已经结束了,我们依然可以访问 i 的值。
为了加强对变量生命周期的控制,ECMAScript 6 引入了块级作用域。
块级作用域存在于:
- 函数内部
- 块中(字符 { 和 } 之间的区域)
let 和 const
块级声明用于声明在指定块的作用域之外无法访问的变量,let 和 const 都是块级声明的一种。
let 和 const的共同特点
1.不会被提升
js
if (false) {
let value = 1;
}
console.log(value); // Uncaught ReferenceError: value is not defined
2.重复声明报错
js
var value = 1;
let value = 2; // Uncaught SyntaxError: Identifier 'value' has already been declared
3.不绑定全局作用域
当在全局作用域中使用 var 声明的时候,会创建一个新的全局变量作为全局对象的属性。
js
var value = 1;
console.log(window.value); // 1
let 和 const 不会这样:
js
let value = 1;
console.log(window.value); // undefined
let 和 const 的区别
const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容。
js
const data = {
value: 1
}
// 没有问题
data.value = 2;
data.num = 3;
// 报错
data = {}; // Uncaught TypeError: Assignment to constant variable.
暂时性死区
临时死区(Temporal Dead Zone),简写为 TDZ
let 和 const 声明的变量不会被提升到作用域顶部,如果在声明之前访问这些变量,会导致报错:
js
console.log(typeof value); // Uncaught ReferenceError: value is not defined
let value = 1;
这是因为 JavaScript 引擎在扫描代码发现变量声明时,要么将它们提升到作用域顶部(遇到 var 声明),要么将声明放在 TDZ 中(遇到 let 和 const 声明)。访问 TDZ 中的变量会触发运行时错误。只有执行过变量声明语句后,变量才会从 TDZ 中移出,然后方可访问。