1. let 声明的全局变量不是全局对象window的属性
这就意味着,你不可以通过 window. 变量名 的方式访问这些变量,而 var 声明的全局变量是 window 的属性,是可以通过 window. 变量名 的方式访问的。
var a = 5
console.log(window.a) // 5
let a = 5
console.log(window.a) // undefined
#2. 用let定义变量不允许重复声明
这个很容易理解,使用 var 可以重复定义,使用 let 却不可以。
var a = 5
var a = 6
console.log(a) // 5
如果是 let ,则会报错
let a = 5
let a = 6
// VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared
// at <anonymous>:1:1
#3. let声明的变量不存在变量提升
function foo() {
console.log(a)
var a = 5
}
foo() //undefined
上述代码中, a
的调用在声明之前,所以它的值是 undefined,而不是 Uncaught ReferenceError。实际上因为 var 会导致变量提升,上述代码和下面的代码等同:
function foo() {
var a
console.log(a)
a = 5
}
foo() //undefined
而对于 let 而言,变量的调用是不能先于声明的,看如下代码:
function foo() {
console.log(a)
let a = 5
}
foo()
// Uncaught ReferenceError: Cannot access 'a' before initialization
在这个代码中, a
的调用是在声明之前,因为 let 没有发生变量提升,所有读取 a 的时候,并没有找到,而在调用之后才找到 let 对 a
的定义,所以按照 tc39 的定义会报错。
#4. let声明的变量具有暂时性死区
只要块级作用域内存在 let
命令,它所声明的变量就绑定在了这个区域,不再受外部的影响。
var a = 5
if (true) {
a = 6
let a
}
// Uncaught ReferenceError: Cannot access 'a' before initialization
上面代码中,存在全局变量 a
,但是块级作用域内 let
又声明了一个局部变量 a
,导致后者绑定这个块级作用域,所以在let声明变量前,对 a
赋值会报错。
ES6 明确规定,如果区块中存在 let
和 const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用 let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
有时“暂时性死区”比较隐蔽,比如:
function foo(b = a, a = 2) {
console.log(a, b)
}
foo()
// Uncaught ReferenceError: Cannot access 'a' before initialization
#5. let 声明的变量拥有块级作用域
let实际上为 JavaScript 新增了块级作用域
{
let a = 5
}
console.log(a) // undefined
a
变量是在代码块 {}
中使用 let 定义的,它的作用域是这个代码块内部,外部无法访问。
if (false) {
var a = 5
}
console.log(a) // undefined
if (false) {
let a = 5
}
console.log(a)
// Uncaught ReferenceError: a is not defined