变量提升
在函数作用域或全局作用域中通过关键字var声明的变量,都会被当成在当前作用域顶部声明的变量。这就是提升机制。
其实在预编译阶段,JavaScript引擎将会把
var value = 6;
提升为
var value;
value = 6;
let块级声明
块级作用域存在于:
- 函数内部
- 块中(
{和}之间)
let 禁止重复声明
在同一作用域中不能用let重复定义已经存在了的标识符。
const
const声明的常量如果是对象,可以修改对象内部的值。也就是不能修改const值的地址,但可以修改地址对象里面的值。
临时死区(Temporal Dead Zone)
JavaScript引擎在扫描代码变量声明时(预编译阶段),要么将他们提升至作用域顶部(var),要么将声明放在临时性死区中(TDZ),下面个两段代码很明确临时死区的存在。
console.log(typeof value) // 会在全局找value,未定义所以为'undefined'
if (condition) {
let value = 'blue'
}
if (condition) {
console.log(typeof value) // Cannot access 'value' before initialization 引用错误
let value = 'blue' // 已经定义,但是在TDZ里面
}
循环中的let声明
之前使用var的时候:
var funs = [];
for( var i = 0; i < 10; i++) {
funcs.push(function(value) {
return function() {
console.log(value)
}
}(i)); // 闭包
}
funcs.forEach(function(func) {
func(); // 输出0、1、2··· 9
})
现在:
var funs = [];
for( let i = 0; i < 10; i++) {
funcs.push(function(value) {
console.log(value)
}
}
funcs.forEach(function(func) {
func(); // 输出0、1、2··· 9
})
let声明在循环内部的行为标准是 专门定义 的,他不一定与let的不提升特性相关!!!
事实上,早期的let实现并不包含这一行为,是后来加入的。
块级绑定的推荐使用
默认使用const,只有确实需要改变变量的值时使用let。
因为大部分声明的值在初始化后不应再改变,而预料外的变量值的改变时很多bug的来源。