ES6学习笔记7:let和const

let和const

let和const是ES6中最重要,最常用的特性之一,let用于定义变量,const用于定义常量,不同于ES5中的var,let的作用域有些变化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f() {
{
let x;
{
// x的值不能被改变
const x = "sneaky";
// 错误,常量的值不可被改变
x = "foo";
}
// 上面的const x的作用域范围被限制在了自身所在的块级作用域中,此处的x是一开始的let x
x = "bar";
// 错误,上面已经声明过了x
let x = "inner";
}
}

let和var的区别

块级作用域

虽然我们之前提到过JavaScript采用的词法作用域,但是ES5中是不存在块级作用域(Block Scope)的,只有函数作用域(Function Scope),因此使用var定义的变量的作用域是自身所在的整个作用域。

来看下面的示例。

1
2
3
4
5
6
7
function foo() {
console.log(v); // undefined
for(var v = 1; v < 10; v ++) {
console.log(v); // v每次循环的值
}
console.log(v); // 10
}

上面代码中,首先解释for循环中v的声明,我们已经知道var的作用域是函数作用域,因此var所在的整个函数都能访问到而不会抛出错误(如第2行和第6行)。再看代码的的第2行,虽然我们这里还没有声明v,但是v已经在JavaScript预编译的过程中将v的声明放到了函数的顶部,但是右赋值操作是发生在解释执行阶段的,因此此时的v虽然已经被声明,但是并没有被赋值,也就是undefined。

1
2
3
4
5
6
7
function bar() {
console.log(v); //error
for(let v = 1; v < 10; v ++) {
console.log(v); // v每次循环的值
}
console.log(v); //error
}

let是基于块级作用域的,因此就很容易解释上面的代码了,for循环里定义的只能在for循环中使用,外部使用则抛出错误。

上述规则同样适用于const。

变量提升

此外,let和const对比var还有一个重要的区别就是不存在变量提升。

1
2
3
4
5
6
7
8
9
10
11
(function() {
'use strict'
console.log(foo); // error
let foo = 3;
}()

(function() {
'use strict'
console.log(foo); // undefined
var foo = 3;
})();

可以看到,如果用let在声明变量之前使用该变量,会抛出错误,而var则不会,这是因为let和const不存在变量提升的关系,而var则存在(注意深入理解的话实际上还有个访问死区的概念,这里简单理解为不存在变量提升即可)。

知识点总结

  1. 熟练使用let和const关键字;
  2. 使用let定义的变量和使用var定义的变量的作用域的区别

参考

  1. BabelJS - Learn ES2015