# let和const关键字
# 块级作用域
# 认识块级作用域
1. 引入:在ES5中,有全局作用域和函数作用域,ES6中,添加了块级作用域。
2. 作用:替换了ES5中匿名立即执行函数表达式。
3. 辨别:{}
内部,if{}
,for{}
花括号内部是块级作用域
4. 本质:let实际上为JS增添了块级作用域
提示
在声明变量时,特别是块级作用域中,最好用const\let,用var会破坏现有规则
# 特点
- 块级作用域内外互不影响(前提是在内部不使用var破坏规则)。
let num = 1;
//块级作用域
{
let num = 2;
console.log(num); //2
}
console.log(num); //1
1
2
3
4
5
6
7
2
3
4
5
6
7
- 块级作用域可以嵌套多层,内层可以读取外层变量,但反之不行。
{{{{
let str = 'Hello';
{
console.log(str);
}}}}}
1
2
3
4
5
2
3
4
5
提示
在for循环中使用let会有一个隐藏的块级作用域嵌套关系: 循环变量那一部分为父作用域,而循环体内部又是一个单独的子作用域。
//用let证明如下:
var arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
//首先加上注释这一行,打印三个hello
// let i = 'hello';
//去掉,打印1, 2, 3
//说明,当子作用域没有i变量后,会往上级找
console.log(i);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 在块级作用域中声明函数,最好要用函数表达式的方式。
提示
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,并且老旧的浏览器不兼容。
{
let fn = function() {
console.log('function is running');
}
fn();
}
1
2
3
4
5
6
2
3
4
5
6
# let
ES6新加关键字,功能上用来替换掉令人头痛的var关键字。其声明的变量,只在所在的块级作用域中有效。
# 特点
- 不存在变量提升
- 有暂时性死区
- 不允许重复声明
# 解析
- 不存在变量提升
let所声明的变量一定要在声明后使用,否则报错。
{
// var中:
console.log(num1); //变量提升,und
var num1 = 1;
}
1
2
3
4
5
6
2
3
4
5
6
{
// let中
console.log(num2); //let不存在变量提升,报错
let num2 = 2;
}
1
2
3
4
5
2
3
4
5
- 暂时性死区(temporal dead zone) TDZ:
如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。 如下:块级作用域中有let,从进入到该块级作用域开始死区开始,直到用let声明完tmp结束。所以从第三行开始就报错。
if (true) {
//TDZ开始
tmp = 'abc';
console.log(tmp);
let tmp; //TDZ结束
console.log(tmp);
tmp = 'def';
console.log(tmp);
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
//再看一个暂时性死区的例子
{
//这里使用let声明变量还没结束,就使用了x所以报错
let x = x;
}
1
2
3
4
5
2
3
4
5
- 不允许重复声明
{
//更改值可以
let test = 'a';
test = 'b';
console.log(test);
//但是重复声明报错
// var test = 'c'
// let test = 'c';
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# const
const
常用来声明常量,既使用const
声明的变量其值不可被更改。
# 特点
- 用const修饰的变量值不可更改。
- 修饰简单类型值不可变化。
- 当其修改时引用数据类型时,地址不可变。
{
//(1) 修饰基本数据类型
const num1 = 1;
// num1 = 2; 报错,不可修改
//(2) 修饰引用数据类型
//理解起来很容易,其实obj内部存储的就是对象的指针,用const修饰的是obj,而不是后面的对象
const obj = {
name: 'jack',
age: 18
}
obj.name = 'Bob'; //可以修改对象内部值
console.log(obj);
// obj = {}; //报错,这里修改了obj内部的指针
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 使用const声明时必须赋予一个值,不然会报错。
- 其他规则与let相同。