let命令的定义
首先,let
命令是 ES6
新增的,也是用来声明变量的,但它与 var
不同的是:“只在 let
命令所在的代码块内有效”。换一句话说就是:“let
命令声明的变量只在当前作用域内有效(包括它的子作用域)”。那么结合它的特征概括起来就是:“let
是 ES6
用来声明只在当前作用域内有效,不存在变量提升,不能重复声明的,会形成暂时性死区变量的一个命令”。
let命令的特征
- 只在当前作用域内有效。
- 不存在变量提升。
- 不能重复声明。
- 暂时性死区。
只在当前作用域内有效
“只在当前作用域内有效”是 let
命令最基本的特征。为了说明什么是只在当前作用域内有效,我们可以看看下面的案例:
if (true) {
var a = 'apple';
let b = 'banana';
}
console.log(a); //apple
console.log(b); //Error: b is not defined
同样是声明一个变量,用 var
声明的可以在 if
语句之外打印出来,而用 let
声明的则报错。这是因为在 ES6
的语法环境当中 if
语句的 “{}
” 部分是一个“块级作用域(如果您还不知道什么是块级作用域,请参考《es6 块级作用域的基本用法》)”,而用 let
声明的变量只在当前作用域内有效,因此在 if
代码块之外输出变量“b”将会报“Error: b is not defined”的错误。
同样的,在下面的块级作用域内,也会有类似的结果。
例一:
//es5语法的var命令
for (var i = 0; i < 10; i++) {
//handle
}
console.log(i); //10
//es6语法的let命令
for (let x = 0; x < 10; x++) {
//handle
}
console.log(x); //Error: x is not defined
例二:
//es5语法的var命令
function testA() {
var a = 'apple';
}
testA();
console.log(a); //Error: a is not defined
//es6语法的let命令
function testB() {
let b = 'banana';
}
testB();
console.log(b); //Error: b is not defined
注意: 函数在 ES5
当中称为“函数作用域”,同样的它也遵守这样的规则:“父作用域不能访问子作用域内声明的变量”。因此,“只在当前作用域内有效”并不是 ES6
特有的,只是在 ES5
语言环境中 if
逻辑判断和 for
循环等语句没有被当做“块级作用域”来解析。
例三:
//es5语法的var命令
{
var a = 'apple';
}
console.log(a); //apple
//es6语法的let命令
{
let b = 'banana';
}
console.log(b); //Error: b is not defined
注意: 成对的“{}
”在 ES6
语言环境中一个“块级作用域”,而在 ES5
中不是。
当然,除了上面的案例以外,还有很多案例都可以能说明“只在当前作用域内有效”这个特征,这里将不在一一列举。
不存在变量提升
在 ES5
语言环境的非严格模式(“use strict
”)中,经常会见到这样的奇葩写法“在var声明的变量之前调用这个变量,然后得到的值通常为undefined”,这种现象通常被成为“变量提升”。按照我们对现实世界的一般逻辑理解是“先有一个事物之后再去使用这个事物”,同样在“代码世界”里,我们同样也这样认为“变量应该在声明语句之后才可以使用”。为了纠正这种“奇葩”现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
//es5语法的var命令
console.log(a); //undefined
var a = 'apple';
//es6语法的let命令
console.log(b); //Error: b is not defined
let b = 'banana';
注意: 上述案例最好在 Chrome
浏览器的控制台( Console
)下直接编写代码进行演示,因为采用 babel
编译器编译后的代码为普通的 ES5
代码,从而导致变量“b”的结果也为“undefined”。
不能重复声明
let
语法规定:“不允许在相同作用域内,重复声明同一个变量。”
例如:
//es5语法的var命令
var a = 'apple';
var a = 'AAAA';
//es6语法的let命令
let b = 'banana';
let b = 'BBBB'; //Error:Duplicate declaration "b"
通过翻译“Duplicate declaration ‘b’”我们可以知道,它的报错意思是:“重复生命了‘b’。”
暂时性死区
结合 let
命令的“不存在变量提升”和“不允许重复声明”这两个特征,我们可以轻松的理解“暂时性死区”这个特征。即:“只要块级作用域内存在let命令,它所声明的变量就‘绑定’(binding)这个区域,不再受外部的影响。”
例如:
var a = 'apple';
;(function () {
a = 'AAA';
var a;
console.log(a); //AAA;
})();
//es6语法的let命令
let b = 'banana';
{
b = 'BBBB'; //Error: bb is not defined
let b;
console.log(b);
}
代码解析:在 ES6
语言环境中 “{}
”是一个块级作用域,由于 let
命令不允许在相同作用域内重复声明同一个变量,以及不存在变量提升的特征,因此上述案例中在 let
命令声明变量“b”之前使用它是错误的。