基本用法
ES6新增了let
命令,用来声明变量。它的用法类似var
,但是所声明的变量,只在let
命令所在的代码块内有效。
{
let a = 10;
var b = 9;
}
a // ReferenceError: a is not defined.
b // 9
上面的代码块里,分别用let
和var
声明了2个变量。然后在代码块之外调用这个2歌变量,结果let
声明的变量报错,var
声明的变量返回了正确的值。这表明let
声明的变量只在它所在的代码块有效。
for
循环的计数器就很适合使用let
命令:
for(let i=0;i<10;i++){}
console.log(i); // ReferenceError: a is not defined.
上面代码中,计数器i
只在for
循环体内里有效,在循环体外引用就会报错。
不存在变量提升
let
不像var
那样会发生“变量提升”现象,所以,变量一定要在声明后使用,否则报错。
console.log(foo); // undefined
console.log(bar); // ReferenceError
var foo = 2;
let bar = 2;
上面代码中,变量foo
用var
命令声明,会发生变量提升,即脚步开始运行时,变量foo
已经存在了,但是没有值,所以会输出undefined
。变量bar
用let
命令声明,不会发生变量提升,这表示在声明它之前,变量bar
是不存在的,这是如果用到它,就会抛出一个错误。
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var tmp = 123;
if(true){
tmp = 'abc'; // ReferenceError
let tmp;
}
上面代码中存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定了这个块级作用域,所以在let
声明变量之前,对tmp
赋值会报错。
“暂时性死区”也意味着typeof
不再是一个百分之百安全的操作:
typeof x; // ReferenceError
let x;
上面的代码中,变量x
使用let
命令声明,所以在声明之前都属于x
的“死区”,只要有用到该变量就会报错。因此,typeof
运行时就会抛出一个ReferenceError
。
作为比较,如果一个变量根本没有被声明,使用typeof
反而不会报错:
typeof xxoo; // "undefined"
所以,在没有let
之前,typeof
运算符是百分之百安全的,永远不会报错。现在这一点不成立了,这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用。
不允许重复声明
// 报错
function (){
let a = 10;
var a= 1;
}
// 报错
function (){
let a = 10;
var a = 1;
}
因此,不能在函数内部重新声明参数:
function func(arg){
let arg; // 报错
}
function func(arg){
{let arg; // 不报错}
}