在 ES6(ECMAScript 2015)中,引入了 let
关键字来声明变量。相比于之前的 var
关键字,let
具有一些独特的声明特性,提供了更好的作用域控制和变量绑定的行为。
块级作用域
使用 let
关键字声明的变量具有块级作用域。块级作用域指的是在代码块(如 {}
中的代码)内部声明的变量只在该块内部有效,并在块外部不可访问。
function example() {
if (true) {
let x = 10;
console.log(x); // 输出: 10
}
console.log(x); // 报错: x is not defined
}
example();
在上面的例子中,使用 let
声明的变量 x
只在 if
代码块内部有效。在 if
代码块外部访问 x
会导致变量未定义的错误。
不变绑定
通过使用 let
声明的变量具有不变绑定的特性。不变绑定意味着在同一个作用域内,无法重新声明具有相同名称的变量。
let x = 10;
let x = 20; // 报错: Identifier 'x' has already been declared
在上面的例子中,尝试重新声明变量 x
会导致重复声明的错误。这与使用 var
声明的变量不同,var
可以在同一作用域内多次声明相同的变量。
暂时性死区
使用 let
声明的变量存在暂时性死区(Temporal Dead Zone,简称 TDZ)的概念。暂时性死区指的是在变量声明之前,变量是不可访问的。
console.log(x); // 报错: Cannot access 'x' before initialization
let x = 10;
在上面的例子中,尝试在变量 x
声明之前访问 x
会导致无法访问的错误。这是因为在 let
声明之前的代码中,变量 x
被认为处于暂时性死区。
循环中的块级作用域
使用 let
在循环中声明的变量会在每次迭代时都创建一个新的变量,形成块级作用域。这在循环中创建闭包时非常有用。
for (let i = 0; i < 3; i ) {
setTimeout(() => {
console.log(i);
}, 1000);
}
// 输出: 0, 1, 2
在上面的例子中,通过使用 let
声明变量 i
,每次循环都会创建一个新的块级作用域,并且在每个迭代中都会绑定一个新的 i
值。这样,每个 setTimeout
回调函数都会捕获到当前迭代的 i
值,输出了预期的结果。