let 关键字不得不说的关键点:
- 不存在变量提升
- 相同作用域内,不允许重复声明一个变量
- 所声明的变量,只在当前作用域有效,超出所在域即over game(块级作用域)
- 在代码块内,使用let命令声明变量之前,该变量都是不可用的(在语法上也可以称之为‘暂时性死区‘)
//1. 不存在变量提升
function f(){
console.log(a); //如果使用var 来声明a变量的话,打印结果应该为undefined
let a = 11;
}
f(); //报错: Uncaught ReferenceError: a is not defined
//2. 相同作用域内,不允许重复声明同一个变量,当然也包括函数参数
function f(x){
console.log(x);
let x = 11;
}
f('a');//报错:Uncaught SyntaxError: Identifier 'x' has already been declared
//但是在不同作用域内不会影响
function test(a){
console.log(a); //12
(function(){
let a = 'hello'
console.log(a); //hello
})();
}
test(12);
//3. 块级作用域
为什么需要块级作用域?
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景
3.1 内层变量可能会覆盖外层变量
var a = 123;
function f(){
console.log(a); //undefined
if(true){
var a = 'another a';
console.log(a); //another a
}
}
f();
//其实本意if 代码块的外部使用外层的a变量,内部使用内层的a变量。但是f执行之后,输出结果为undefined,原因在于变量提升,导致内层的a变量覆盖了外层的a变量
3.2 用来计数的循环变量泄漏为全局变量
var str = 'haha';
for(var i = 0; i < str.length; i++){
console.log(str[i]);
}
console.log(i); //4
//变量i 只用来控制循环,但是循环结束之后,它并没有消失,泄漏成了全局变量
4.暂时性死区
let a = 'abc';
if(true){
a = 12;// 报错:Uncaught ReferenceError: a is not defined
let a;
}
//存在全局变量a,但是在if代码块内 let又声明了一个局部变量a,而在let声明变量之前,使用了这个变量导致报错
ES6规定,如果区块中存在let命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域,凡是在声明之前就是用这些变量,就会报错;
总之,暂时性死区的本质就是:只要已进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量