写作不易,Star是最大鼓励,感觉写的不错的可以给个Star⭐,请多多指教。本博客的Github地址。
在项目中尽可能使用const,如果某个值需要更改才使用let。
var的缺陷
- var声明的变量(函数作用域除外)会挂载到全局(挂载到window对象上),会污染全局变量。但是let声明的变量不会污染全局变量,并不会挂载到window对象上。
- 变量声明提升,可以在声明之前调用(函数声明提升、变量提升)
- 可以重复声明(是指在同一个作用域下可以重复声明)
- 没有块级作用域
- 无法限制修改(const可以声明一个常量来限制修改)
需要注意:函数作用域中var声明的变量是局部变量,直接在全局作用域中访问不到。
let和const
- 都不能重复声明
- 都是块级作用域,{}块内声明的,块外访问无效
- let声明的是变量,可以修改
- const声明的是常量,不能修改
let a = 1;
let a = 2;
console.log(a); // Identifier 'a' has already been declared
1
2
3
2
3
const name = 'lisi';
name = 'wangwu'; // Uncaught TypeError: Assignment to constant variable.
1
2
2
// 虽然obj不能被重新赋值,但是其属性可以
const obj = {
name: 'lisi',
age: 12
};
obj.name = 'wangwu';
console.log(obj); // {name: "wangwu", age: 12}
1
2
3
4
5
6
7
2
3
4
5
6
7
const obj = {
name: 'lisi',
age: 12
};
Object.freeze(obj); // 使得obj的属性不能被修改
obj.name = 'wangwu';
console.log(obj); // { name: 'lisi', age: 12 }
1
2
3
4
5
6
7
2
3
4
5
6
7
来看个🌰:
var a = 1;
{
var a = 2; // es5没有块级作用域,这里的声明会覆盖花括号上面的声明
}
console.log(a); // 2
1
2
3
4
5
2
3
4
5
// 这里b是在不同的作用域下进行了两次声明
let b = 2; // 全局作用域下的b
{ // 块级作用域
// console.log(b); // Uncaught ReferenceError: Cannot access 'a' before initialization
// 报错,暂时性死区
// 块级作用域中的b
let b = 3; // 这里的b和花括号外面的b不一样,可以用babel编译一下就可以看出来
}
console.log(b); // 2 这里获取的是全局作用域中的b
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
需要注意:let声明的变量也会被提升到其所在的块级作用域的顶部,但是因为存在暂时性死区,所以在声明之前引用会报错。
需要注意:var声明的变量会声明到全局,挂载到window对象上,但是let声明变量并不会挂载到window对象上。
## 使用let和const代替IIFE(立即执行函数)
IIF的主要作用之一就是用来生成一个私有变量。这样做的目的是为了防止var声明的变量污染全局变量。
```js
(function() {
var a = 123;
})();
console.log(a); // ReferenceError: a is not defined
```
下面使用let来实现:
```js
{
let a = 123;
}
console.log(a); // ReferenceError: a is not defined
```
## 块级作用域举例
```js
// var i = 0;会把a声明到全局
for (var i = 0; i < 10; i++) {
// 作用域链
setTimeout(() => {
console.log(i); // 打印出10个10,因为全局只有一个i
}); // 最小延迟4ms
}
for (let i = 0; i < 10; i++) {
// 作用域链
// 这里for循环产生了10个块级作用域,每个块级作用域都有自己的i
setTimeout(() => {
// i的查找:当前作用域没有找到i,会沿着作用域链向上查找
console.log(i); // 打印0-9
}); // 最小延迟4ms
}
```
```html
```
* 原来用var的方式,结果弹出的都是3
* 或者将变量封装到函数里,限制作用域,但比较麻烦
* 用let最简单,直接var改let,解决作用域问题← 首页 2. Set和Map→