Appearance
二、变量声明:let 与 const
var 的问题
在 ES6 之前,JavaScript 中只有 var 一种变量声明方式,但它存在以下问题:
1. 变量提升
javascript
console.log(a); // undefined,而不是报错
var a = 10;2. 重复声明
javascript
var a = 10;
var a = 20; // 不会报错,会覆盖之前的值
console.log(a); // 203. 作用域混乱
var 只有函数作用域,没有块级作用域:
javascript
if (true) {
var b = 20;
}
console.log(b); // 20,在块外也能访问let 声明变量
let 是 ES6 引入的新变量声明方式,解决了 var 的问题:
1. 块级作用域
javascript
if (true) {
let c = 30;
}
console.log(c); // 报错:c is not defined2. 不能重复声明
javascript
let d = 40;
let d = 50; // 报错:Identifier 'd' has already been declared3. 不存在变量提升
javascript
console.log(e); // 报错:e is not defined
let e = 60;const 声明常量
const 用于声明常量,即不可变的值:
1. 只读
javascript
const f = 70;
f = 80; // 报错:Assignment to constant variable.2. 必须赋值
javascript
const g; // 报错:Missing initializer in const declaration3. 引用类型可修改
对于引用类型(对象、数组),const 只保证引用地址不变,内部属性可以修改:
javascript
const obj = { name: 'ES6' };
obj.name = 'ES7'; // 可以修改
console.log(obj.name); // ES7
const arr = [1, 2, 3];
arr.push(4); // 可以修改
console.log(arr); // [1, 2, 3, 4]let / const / var 三者区别总结
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 存在 | 不存在 | 不存在 |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 重新赋值 | 允许 | 允许 | 不允许(引用类型内部可修改) |
| 初始值 | 可选 | 可选 | 必须 |
实战案例:块级作用域与循环问题
问题:使用 var 的循环变量泄露
javascript
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 输出 3, 3, 3
}, 1000);
}解决方案:使用 let
javascript
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i); // 输出 0, 1, 2
}, 1000);
}解释
- 使用
var时,循环变量i是函数作用域,在循环结束后变为 3,所以三个 setTimeout 回调都输出 3 - 使用
let时,循环变量i是块级作用域,每次循环都会创建一个新的i,所以输出 0, 1, 2
最佳实践
- 优先使用 const:对于不需要重新赋值的变量,使用 const
- 其次使用 let:对于需要重新赋值的变量,使用 let
- 尽量避免使用 var:var 存在诸多问题,在现代 JavaScript 中应尽量避免使用
通过本章节的学习,你已经掌握了 ES6 中变量声明的新方式。let 和 const 解决了 var 的许多问题,使代码更加安全和可维护。
