Skip to content

var、let、const区别

总结对比表

varletconst 都是JavaScript 中用来声明变量的关键字,现代开发中,优先使用 const,如果变量需要被重新赋值,则使用 letvar已经逐步**放弃使用了。 **

主要区别如下

特性varletconst
作用域函数作用域块级作用域块级作用域
变量提升提升 (值为 undefined)不提升 (存在 TDZ)不提升 (存在 TDZ)
重复声明允许不允许不允许
初始化可选可选必须
重新赋值允许(默认undefined)允许(默认undefined)不允许
挂载到window

var、let、const对比

1. 作用域

  • var:函数作用域
    • 只有在函数内部声明的 var 变量才是局部变量,在块级作用域(如 ifforwhile 代码块)中声明的 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 declared

4. 初始化与赋值

  • 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
    • 在全局作用域声明的 letconst 变量,不会挂载到 window 对象上,它们存在于一个新的概念“Script”作用域中。
javascript
var a = 1;
let b = 2;
console.log(window.a); // 输出 1
console.log(window.b); // 输出 undefined

开发建议

  1. **默认使用 **const:绝大多数变量在声明后都不应该被改变,使用 const 可以让代码意图更清晰,也更安全。
  2. **其次使用 **let:只有当你明确知道变量的值会在后续代码中被修改时(如循环计数器 for (let i=0...)),才使用 let
  3. **禁止使用 **var:为了代码的可维护性和避免潜在 Bug,现代 JavaScript 开发(ES6+)中已经不再需要 var

Released under the MIT License.