基本用法
-
let 的使用方法类似于 var,并可以代替 var 来声明变量
{ let name = '张三'; }
-
var 对比 let
// 1. var 声明的变量只能在全局或者整个函数块中 // 2. var 会在全局声明时创建 window 对象的属性,var 是没有块的概念的,声明的变量会是 window 对象上的属性,在最外层的 window 上可以取到 // 3. var 在同一个块级下可以重复地声明一个变量 { var name = '张三' // 张三 var name = '李四' // 李四 } console.log(window.name) // 李四 // 1. let 允许你声明一个作用域被限制在块级中的变量、语句或者表达式 // 2. let 不会在全局声明时创建 window 对象的属性,会报错 // 3. let 在同一个块级下不能重复地声明一个变量 { let age = 10 // 10 let age = 18 // Uncaught SyntaxError: Identifier 'age' has already been declared } console.log(window.age) // undefined
块级作用域
在深入了解 let 前,需要了解一下,在 JavaScript 中有哪些作用域:
- 全局作用域
- 函数作用域 / 局部作用域
- 块级作用域
在 ES5 中的作用域有全局作用域和函数作用域,而块级作用域是 ES6 的概念;
全局作用域
全局作用域就是在任何地方都能访问到它,在浏览器中能通过 window 对象拿到的变量就是全局作用域下声明的变量
使用 var 定义的变量,可以在 window 对象上拿到此变量,这里的 name 就是全局作用域下的变量
var name = '张三';
console.log(window.name) // 张三
函数作用域
函数作用域就是在函数内部定义的变量,也就是局部作用域,在函数的外部是不能使用这个变量的,也就是对外是封闭的,从外层是无法直接访问函数内部的作用域的
在函数内部定义的 name 变量,在函数外部是访问不了的,要想在函数外部访问函数内部的变量可以通过 return 的方式返回出来
function bar() {
var name = '张三';
}
console.log(name); // undefined
块级作用域
块级作用域是 ES6 的概念,它的产生是要有一定的条件的,在大括号 {} 中,使用 let 或 const 声明的变量,才会产生块级作用域
块级作用域的产生是 let 或 const 带来的,而不是大括号,大括号的作用是限制 let 或 const 的作用域范围
-
可以看出 {} 内外是互不干涉和影响的,如果在声明 num 的前面进行打印的话,还会报错,这个时候 num 处于暂存死区,是不能被使用的
let num = 10; { console.log(num); // Uncaught ReferenceError: Cannot access 'num' before initialization let num = 20; console.log(num); // 20 } console.log(num); // 10
-
块级作用域可以任意嵌套,每一层都是一个单独的作用域,内层作用域可以读取外层的变量,而外层无法读取内层的变量
{{ let x = 'Hello 张三' { console.log(x); // Hello 张三 let y = 'Hello World' } console.log(y); // 引用错误 ReferenceError: y is not defined. }};
-
使用 let 方式声明的变量在 window 下是取不到的
let name = '张三'; console.log(window.name) // undefined
-
在使用 var 声明的情况下,可以看出,外层的 num 会被 {} 中的 num 覆盖,所以没有块级作用域的概念
var num = 10; { var num = 20; console.log(num) // 20 } console.log(num) // 20
不能变量提升
-
var 可以变量提升的,提升到作用域的最顶部,作用域是全局,使得声明变量前也可以使用,但值为 undefined
{ console.log(bar); // 输出 undefined,没有值但不会报错 var bar = 1; }
-
一般变量都应该先声明再使用,所以 let 和 const 语法规定必须声明后使用
{ console.log(name); // 引用错误 ReferenceError: name is not defined. let name = '张三'; // 由于 let 不能进行变量提升所以会报引用错误 }
暂时性死区
-
在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区” (temporal dead zone,简称 TDZ)
{ console.log(name); // ReferenceError: name is not defined. let name = '张三'; console.log(name); // 张三 }
-
对于 typeof 也是会报错的
{ console.log(typeof name); // Uncaught ReferenceError: Cannot access 'name' before initialization let name = '张三'; }
重复声明报错
-
let 不允许在同一个函数或块作用域中重复声明同一个变量,否则会引起语法错误 (SyntaxError)
{ let x = 10; let x = 11; } // Uncaught SyntaxError: Identifier 'x' has already been declared
-
即使使用 var 去声明也是不可以的,当使用 let 声明的时候 x 已经是一个死区了,不可以被重复声明了
{ let x = 10; var x = 1; }
-
在 switch 语句中只有一个块级作用域,所以下面这种情况也是会报错的
let x = 1; switch(x) { case 0: let num; break; case 1: let num; // 重复声明了 break; } // 报错
-
case 后面的语句 let 变量声明在放到块中,是单独的作用域,所以就不会报错
let x = 1; switch(x) { case 0: { // 块 let num; break; } case 1: { // 块 let num; // 这里就没有关系了,可以正常声明 break; } }
小结
let 只作用于块级作用域内;
let 声明的变量不能进行变量提升,存在暂存死区;
let 声明的变量不允许重复声明,无论重复用 var 或者其他声明都不行;
尽量使用 let 去代替 var 来声明变量;
🌿 GIT 分支、标签
上一篇