var-let-const

一阅 1处


使用 var 的问题

1)声明的变量默认声明到全局(会污染全局作用域)

作用域分为:全局作用域、函数作用域

1
2
3
var a = 1;
// window.a; 这是全局作用域中的a
// 当我们想把a放在作用域里面 可以套一个函数

let + {}

1
2
3
4
5
6
7
8
9
10
{
let a = 1;
console.log(a);
}
console.log("外面", a);
/* 打印结果:
1
a is not defined
*/
// 如上 {}作用域 + let 可以实现一个作用域

var + {}

1
2
3
4
5
6
7
8
9
10
{
console.log(a);
var a = 1;
}
console.log("外面", a);
/* 打印结果:
undefined
外面 1
*/
// 这里line3 用var声明的变量会导致变量提升, 所以line2可以打印,因为已经声明了,只是line3才赋值,所以没有打印出1
2)用var声明的变量会提升 var function import 这3种都会导致变量提升,用let声明的变量会绑定到当前作用域 暂存死区

我们希望像如上这样可以报错,因为a还没有声明 所以可以如下:

1
2
3
4
5
6
7
8
{
console.log(a);
let a = 1;
}
console.log("外面", a);
/*打印结果:
line2会报错 ReferenceError: a is not defined
*/

var VS let

1
2
3
4
5
6
7
8
// var
var a = 2;
{
console.log(a);
var a = 1;
}
console.log("外面", a);
// 打印结果: 2 外面 1
1
2
3
4
5
6
7
8
9
10
11
// let
let a = 2;
{
console.log(a);
let a = 1;
}
console.log("外面", a);
/*打印结果:
line4会报错 ReferenceError: a is not defined
*/
// 可以看出 还是会报错 这是因为用let声明的变量会绑定到当前作用域 当前{}作用域(line3-6)下已经有a了,就不会往上级作用域查找

*****当line5注释掉之后,可以看到返回 2 外面 2 向上级作用域查找了

1
2
3
4
5
6
7
8
// let
let a = 2;
{
console.log(a);
// let a = 1;
}
console.log("外面", a);
// 执行结果: 2 外面 2

当前这个都是es6语法 要把es6转化成es5需要转化器 babel, 就会把let转化为var 就会输出 2 外面 1

3)当var a = 1; var a = 2;时后面的变量会把前面的覆盖掉,如果引用了别人的代码 若变量名相同会把别人的代码覆盖,所以这里用let 可以保证命名不重
1
2
3
let a = 1;
let a = 2;
//执行结果: SyntaxError: Identifier 'a' has already been declared

小示例

1
2
3
4
5
6
let fn = function a(){

}
console.log(a);
// 执行结果: ReferenceError: a is not defined
// 这里这个a不能调用函数,fn可以 这里的a只是改变了这个匿名函数的名称 不能改变他的声明变量
4) var a = 1; a = 100; var声明的变量可以被更改 希望不被更改用const
1
2
3
4
5
const obj = {};
obj = 1; // 会报错
obj.b = 2; // 不会报错
console.log(obj);
// 不改变空间指向的值就不会报错

什么时候用const let, 尽可能用const 如果整个值需要改变 则使用let

5) 自执行函数可以解决作用域问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for(var i = 0; i< 10; i++){
setTimeout(()=>{
console.log(i);
}) // 默认不给时间 是 >=4ms
}
// 执行结果: 10 10 10 10 10 10 10 10 10 10
// 解决办法 如果是以前会这样
for(var i = 0; i< 10; i++){
(function(i){
setTimeout(()=>{
console.log(i);
})
})(i)
}
// 执行结果:0 1 2 3 4 5 6 7 8 9
// 这里将i放到函数作用域保存起来 所以能够拿到

用let的方法解决

1
2
3
4
5
6
for(let i = 0; i< 10; i++){
setTimeout(()=>{
console.log(i);
})
}
// 执行结果:0 1 2 3 4 5 6 7 8 9