let命令
ES6 新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
for循环中let命令的使用:
var a = [];
for (var i = 0; i < 3; i++) {
a[i] = function () {
return i;
};
}
console.table([
a[0],a[1],a[2]
])
结果:
上面代码中,变量i
是var
命令声明的,在全局范围内都有效,所以全局只有一个变量i
。每一次循环,变量i
的值都会发生改变,里面的i
指向的就是全局的i
。也就是说,所有数组a
的成员里面的i
,指向的都是同一个i
,导致运行时输出的是最后一轮的i
的值,也就是 4。
var a = [];
for ( let i = 0; i < 3; i++) {
a[i] = function () {
return i+1;
};
}
console.table([
a[0](),a[1](),a[2]()
])
结果:
上面代码中,变量i
是let
声明的声明的变量仅在块级作用域内有效,也就是当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量。
let命令不存在变量提升
var
命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined
。let
命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
暂时性死区
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
var test = 1;
if(1){
test = 2; //ReferenceError
let test = 4;
}
上面代码中,存在全局变量test,但是块级作用域内let
又声明了一个局部变量test
,导致后者绑定这个块级作用域,所以在let
声明变量前,对test
赋值会报错。
ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
不允许重复声明变量
let
不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
不许在函数内部重新声明参数
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
本文参考:ECMAScript 6 入门-阮一峰