var、let、const区别
总结对比表
var、let 和 const 都是JavaScript 中用来声明变量的关键字,现代开发中,优先使用 const,如果变量需要被重新赋值,则使用 let,var已经逐步**放弃使用了。 **
主要区别如下
| 特性 | var | let | const |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 提升 (值为 undefined) | 不提升 (存在 TDZ) | 不提升 (存在 TDZ) |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 初始化 | 可选 | 可选 | 必须 |
| 重新赋值 | 允许(默认undefined) | 允许(默认undefined) | 不允许 |
| 挂载到window | 是 | 否 | 否 |
var、let、const对比
1. 作用域
var:函数作用域- 只有在函数内部声明的
var变量才是局部变量,在块级作用域(如if、for、while代码块)中声明的var变量会“泄露”到外部。
- 只有在函数内部声明的
let** /const:块级作用域**- 只在当前的代码块(
{}内部)有效。这更符合其他编程语言(如 Java、C++)的习惯,能有效防止变量污染。
- 只在当前的代码块(
js
// var 的例子
function testVar() {
if (true) {
var a = 10;
}
console.log(a); // 输出 10 (if 块结束后依然可以访问)
}
// let/const 的例子
function testLet() {
if (true) {
let b = 20;
const c = 30;
}
// console.log(b); // 报错: ReferenceError: b is not defined
// console.log(c); // 报错: ReferenceError: c is not defined
}2. 变量提升
var:存在变量提升- 在代码执行前,
var声明的变量会被提升到函数或全局作用域的顶部,但赋值不会提升。此时变量的值是undefined。
- 在代码执行前,
let** /const:存在“暂时性死区”**- 虽然它们在声明前也会被放入词法环境,但从代码块开始到变量声明语句之间,访问这些变量会直接报错。这个区域被称为“暂时性死区”。
javascript
console.log(myVar); // 输出 undefined (变量提升,但未赋值)
var myVar = 10;
console.log(myLet); // 报错: ReferenceError: Cannot access 'myLet' before initialization (TDZ)
let myLet = 20;3. 重复声明
var:允许重复声明- 在同一作用域内,可以多次使用
var声明同一个变量,后声明的会覆盖前面的(这很容易导致 Bug)。
- 在同一作用域内,可以多次使用
let** /const:不允许重复声明**- 在同一作用域内,重复声明同一个变量会直接报错。
javascript
var a = 1;
var a = 2; // 合法,a 变为 2
let b = 1;
// let b = 2;
// 报错: SyntaxError: Identifier 'b' has already been declared4. 初始化与赋值
var** / **let- 声明时可以不初始化(不赋值),默认值为
undefined。 - 声明后,可以任意修改其值。
- 声明时可以不初始化(不赋值),默认值为
const- 声明时必须初始化(必须赋值),否则会报错。
- 声明后,不允许重新赋值(指针不可变)
- 注意:如果
const声明的是一个引用类型(对象或数组),虽然不能修改指针指向的地址,但可以修改对象内部的属性或数组的内容。
javascript
// let
let x;
x = 10; // 合法
x = 20; // 合法
// const
// const y; // 报错: Missing initializer in const declaration
const y = 100;
// y = 200; // 报错: Assignment to constant variable.
// const 引用类型的特例
const person = { name: "Alice" };
person.name = "Bob"; // 合法!修改的是对象属性,不是变量指向的地址
// person = {}; // 报错!试图修改变量指向的地址5. 全局对象属性
var- 在全局作用域声明的
var变量,会自动成为window对象(浏览器环境)的属性。
- 在全局作用域声明的
let** / **const- 在全局作用域声明的
let和const变量,不会挂载到window对象上,它们存在于一个新的概念“Script”作用域中。
- 在全局作用域声明的
javascript
var a = 1;
let b = 2;
console.log(window.a); // 输出 1
console.log(window.b); // 输出 undefined开发建议
- **默认使用 **
const:绝大多数变量在声明后都不应该被改变,使用const可以让代码意图更清晰,也更安全。 - **其次使用 **
let:只有当你明确知道变量的值会在后续代码中被修改时(如循环计数器for (let i=0...)),才使用let。 - **禁止使用 **
var:为了代码的可维护性和避免潜在 Bug,现代 JavaScript 开发(ES6+)中已经不再需要var。