In this article

In this article

尝试一下

let x = 1;

if (x === 1) {

let x = 2;

console.log(x);

// Expected output: 2

}

console.log(x);

// Expected output: 1

语法

jslet name1;

let name1 = value1;

let name1 = value1, name2 = value2;

let name1, name2 = value2;

let name1 = value1, name2, /* …, */ nameN = valueN;

参数

nameN

要声明的变量的名称。必须是合法的 JavaScript 标识符或解构绑定模式。

valueN 可选

变量的初始值。可以是任意合法的表达式。默认值为 undefined。

描述

用 let 声明的变量的作用域是最靠近并包含 let 声明的以下花括号闭合语法结构的一个:

块语句

switch 语句

try...catch 语句

let 位于其开头的 for 语句之一的主体

函数主体

类静态初始化块

如果不是以上这些情况则是:

当代码以模块模式运行时,作用域是当前模块。

当代码以脚本模式运行时,作用域是全局作用域。

相较于 var,let 声明有以下不同点:

let 声明的作用域是块或函数。

let 声明的变量只能在执行到声明所在的位置之后才能被访问(参见暂时性死区)。因此,let 声明通常被视为是非提升的。

let 声明在脚本的顶级作用域上声明变量时不会在全局对象上创建属性。

let 声明的变量不能被同一个作用域中的任何其他声明重复声明。

let 是声明,而不是语句的开头。这意味着,你不能将单独的 let 声明当做块的主体使用(因为这样做会让变量无法被访问)。

jsif (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context

注意:在非严格模式下允许将 let 作为 var 或者 function 的标识符名称,但你应当避免将 let 用作标识符以防止发生意外的语法混淆。

许多风格指南(包括 MDN 的)推荐只要变量没有在其作用域中被重新赋值,就应该使用 const 而不是 let。这样能更清楚地表明变量的类型(或值,如果其为原始值)永远不会改变。此外也推荐用 let 存放可变的非原始值。

let 关键字后方的列表叫做绑定列表,使用逗号分隔,其中的逗号不是逗号运算符,并且 = 符号也不是赋值运算符。后初始化的变量能够引用列表中之前初始化的变量。

暂时性死区

用 let、const 或 class 声明的变量可以称其从代码块的开始一直到代码执行到变量声明的位置并被初始化前,都处于一个“暂时性死区”(Temporal dead zone,TDZ)中。

当变量处于暂时性死区之中时,其尚未被初始化,并且任何访问其的尝试都将导致抛出 ReferenceError。当代码执行到变量被声明的位置时,变量会被初始化为一个值。如果变量声明中未指定初始值,则变量将被初始化为 undefined。

这与 var 声明的变量不同,如果在声明位置前访问 var 声明的变量会返回 undefined。以下代码演示了在声明位置前访问 let 和 var 声明的变量的不同结果。

js{

// 暂时性死区始于作用域开头

console.log(bar); // "undefined"

console.log(foo); // ReferenceError: Cannot access 'foo' before initialization

var bar = 1;

let foo = 2; // 暂时性死区结束(对 foo 而言)

}

使用“暂时性”一词是因为这个区域取决于代码执行的时间点,而不是代码编写的顺序。例如,下面的代码能够运行,是因为虽然使用 let 变量的函数写在变量声明之前,但函数是在暂时性死区外面被调用的。

js{

// 暂时性死区始于作用域开头

const func = () => console.log(letVar); // 没问题

// 在暂时性死区内访问 letVar 会抛出 `ReferenceError`

let letVar = 3; // 暂时性死区结束(对 letVar 而言)

func(); // 在暂时性死区外调用

}

在暂时性死区内对 let 声明的变量使用 typeof 运算符也会抛出 ReferenceError:

jstypeof i; // ReferenceError: Cannot access 'i' before initialization

let i = 10;

这与对未声明的变量和存放 undefined 值的变量使用 typeof 运算符不同:

jsconsole.log(typeof undeclaredVariable); // "undefined"

备注:let 和 const 声明仅在当前脚本被处理时才会被处理。如果在一个 HTML 中有两个以脚本模式运行的