1. 函数作用域与块级作用域

在ES6出现之前,JavaScript是没有块级作用域的概念的。ES6的横空出世带来了let和const代替之前的var声明变量和常量,由此也带来了块级作用域的概念。

我们来看代码:

1
2
3
4
5
{
var a = 23
console.log(a);
}
console.log(a);

上述输出两个23;

再来看let和const声明形式:

1
2
3
4
5
6
7
8
{
let a = 23;
const NUM = 6;
console.log(a);
console.log(NUM);
}
console.log(a);
console.log(NUM);

上述输出如下:

很明显,在大括号外输出变量a和常量NUM是直接报错,没有定义!这已经充分说明let和const声明的变量具有块级作用域。

2. 关于变量提升

我们知道由var声明的变量和function声明的函数会提升到当前作用域的最前边,而ES6出现的let和const声明的变量是不会进行提升的,请看代码:

1
2
console.log(a);   // undefined
var a = 23

变量a用var的方式声明,var声明的变量会提升到当前作用域的最前方,上述代码实际会变成如下:

1
2
3
var a;
console.log(a); // undefined
a = 23

再来看let和const声明的变量:

1
2
3
4
console.log(a);
console.log(b);
const a = 21
let b = 26

上述代码,会报错!在let和const声明之前就使用其声明的变量,会报错,这充分说明了let和const不存在变量提升;其实let和const会存在暂时性死区,在其所在的作用域内,直到其声明的地方之前,都不允许出现其要声明的变量,即暂时性死区,这更加充分的说明了let和const不存在变量提升。

3. 在for循环中的区别

1
2
3
4
for (var i = 0; i < 99; i++) {
console.log(i);
}
console.log(i);

由 var 声明的变量,在for循环之外,依然可以拿到变量 i 的值。

我们再来看由 let 声明的变量:

1
2
3
4
for (let i = 0; i < 99; i++) {
console.log(i);
}
console.log(i);

上述代码在for循环之外输出变量 i 的值会报错,因为 let 声明的变量具有块级作用域的关系,所以在 for 循环中用 let 声明变量,在for循环之外是拿不到 i 的值的,换句话说就是不会污染for循环之外的变量。所以强烈建议各位同学在使用for循环时使用let声明循环变量。

4. 全局声明,var声明的会成为window对象的属性,let则不会

直接上代码,不罗嗦:

1
2
3
4
var a = 23
console.log(window.a); // 23
let b = 32
console.log(window.b); // undefined

结论很明显,var声明的变量会挂载到全局对象window上,而let声明的变量则不会挂载在window对象上。