let
语句声明一个块级作用域的局部变量,并可以初始化为一个值(可选)。
欢迎各位兄弟 发布技术文章
这里的技术是共享的
let
语句声明一个块级作用域的局部变量,并可以初始化为一个值(可选)。
要声明的一个或多个变量的名称,必须是合法的标识符。 变量的初始值,可以是任意合法的表达式。 另外,也可以使用解构赋值语法来声明变量。 就像 可以从这里了解我们为什么使用 通过在使用 与 在全局作用域中, 在同一个函数或块作用域中重复声明同一个变量会抛出 在 然而,需要特别指出的是,一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境,就不会产生上诉重复声明的错误。 从一个代码块的开始直到代码执行到声明变量的行之前, 当变量处于暂时性死区之中时,其尚未被初始化,尝试访问变量将抛出 与 使用术语“temporal”是因为区域取决于执行顺序(时间),而不是编写代码的顺序(位置)。例如,下面的代码会生效,是因为即使使用 如果使用 这与使用 以下代码会导致 由于外部变量 在以下情况下,这种现象可能会使您感到困惑。 在没有执行到它的初始化语句之前,它仍旧存在于暂时性死区中。 用在块级作用域中, 然而,尝试一下
语法
let name1 [= value1] [, name2 [= value2]] [, ..., nameN [= valueN];
参数
nameN
valueN
可选let { bar } = foo; // where foo = { bar:10, baz:12 };
/* 创建一个名为 'bar' 的变量,其值为 10 */
描述
let
允许你声明一个作用域被限制在块
作用域中的变量、语句或者表达式。与 var
关键字不同的是,var
声明的变量作用域是全局或者整个函数块的。 var
和 let
的另一个重要区别,let
声明的变量不会在作用域中被提升,它是在编译时才初始化(参考下面的暂时性死区)。const
一样,let
不会在全局声明时(在最顶层的作用域)创建 window
对象的属性。let
。let
变量的作用域顶部声明它们,可以避免很多问题,但这样做可能会影响可读性。var
不同的是,let
只是开始声明,而非一个完整的表达式。这意味着你不能将单独的 let
声明作为一个代码块的主体(这是有道理的,因为声明的变量无法被访问)。if (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
示例
作用域规则
let
声明的变量作用域只在其声明的块或子块内部,这一点,与 var
相似。二者之间最主要的区别在于 var
声明的变量的作用域是整个封闭函数。function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
let
和 var
不一样,它不会在全局对象上创建属性。例如:var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
重复声明
SyntaxError
。if (x) {
let foo;
let foo; // SyntaxError thrown.
}
switch
语句中也会触发这个错误,因为它是同一个块作用域。let x = 1;
switch(x) {
case 0:
let foo;
break;
case 1:
let foo; // SyntaxError for redeclaration.
break;
}
let x = 1;
switch(x) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}
暂时性死区
let
或 const
声明的变量都处于“暂时性死区”(Temporal dead zone,TDZ)中。ReferenceError
。当代码执行到声明变量所在的行时,变量被初始化为一个值。如果声明中未指定初始值,则变量将被初始化为 undefined
。var
声明的变量不同,如果在声明前访问了变量,变量将会返回 undefined
。以下代码演示了在使用 let
和 var
声明变量的行之前访问变量的不同结果。{ // TDZ starts at beginning of scope
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2; // End of TDZ (for foo)
}
let
变量的函数出现在变量声明之前,但函数的执行是在暂时性死区的外面。{
// TDZ starts at beginning of scope
const func = () => console.log(letVar); // OK
// Within the TDZ letVar access throws `ReferenceError`
let letVar = 3; // End of TDZ (for letVar)
func(); // Called outside TDZ!
}
暂时性死区与
typeof
typeof
检测在暂时性死区中的变量,会抛出 ReferenceError
异常:// results in a 'ReferenceError'
console.log(typeof i);
let i = 10;
typeof
检测值为 undefined
的未声明变量不同:// prints out 'undefined'
console.log(typeof undeclaredVariable);
暂时性死区和词法作用域
ReferenceError
:function test() {
var foo = 33;
if(foo) {
let foo = (foo + 55); // ReferenceError
}
}
test();
foo
有值,因此会执行 if
语句块,但是由于词法作用域,该值在块内不可用:if
块内的标识符 foo
是 let foo
。表达式 (foo + 55)
会抛出 ReferenceError
异常,是因为 let foo
还没完成初始化,它仍然在暂时性死区里。let n of n.a
已经在 for 循环块的私有范围内,因此,标识符 n.a
被解析为位于指令本身(let n
)中的“n
”对象的属性“a
”。function go(n) {
// n here is defined!
console.log(n); // Object {a: [1,2,3]}
for (let n of n.a) { // ReferenceError
console.log(n);
}
}
go({a: [1, 2, 3]});
其它情况
let
将变量的作用域限制在块内,而 var
声明的变量的作用域是在函数内。var a = 1;
var b = 2;
if (a === 1) {
var a = 11; // the scope is global
let b = 22; // the scope is inside the if-block
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
var
与 let
合并的声明方式会抛出 SyntaxError
错误,因为 var
会将变量提升至块的顶部,这会导致隐式地重复声明变量。let x = 1;
{
var x = 2; // SyntaxError for re-declaration
}
Specification |
---|
ECMAScript Language Specification # sec-let-and-const-declarations |
Report problems with this compatibility data on GitHub
Tip: you can click/tap on a cell for more information. Full support Partial support See implementation notes. Has more compatibility info.Legend
参见