写作不易,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
const name = 'lisi';
name = 'wangwu'; // Uncaught TypeError: Assignment to constant variable.
1
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
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

来看个🌰:

var a = 1;
{
    var a = 2; // es5没有块级作用域,这里的声明会覆盖花括号上面的声明
}
console.log(a); // 2
1
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

需要注意: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,解决作用域问题