JavaScript 中 let/const/var 的区别

8 阅读2分钟

JavaScript 中 let/const/var 的区别

变量声明方式比较

特性varletconst
作用域函数作用域块级作用域块级作用域
变量提升否(暂时性死区)否(暂时性死区)
重复声明允许不允许不允许
初始化要求不需要不需要必须初始化
全局声明时成为全局对象属性不成为全局对象属性不成为全局对象属性
变量修改可以可以不可以(对象内部属性可修改)

详细解析

1. 作用域

var: 函数作用域 (Function Scope)

function varTest() {
  var x = 1;
  if (true) {
    var x = 2; // 同一个变量
    console.log(x); // 2
  }
  console.log(x); // 2
}

let/const: 块级作用域 (Block Scope)

function letTest() {
  let x = 1;
  if (true) {
    let x = 2; // 不同的变量
    console.log(x); // 2
  }
  console.log(x); // 1
}

2. 变量提升

var: 存在变量提升

console.log(a); // undefined (不会报错)
var a = 1;

// 等同于:
var a;
console.log(a); // undefined
a = 1;

let/const: 不存在变量提升,有"暂时性死区"

console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 2;

// const 表现相同
console.log(c); // ReferenceError: Cannot access 'c' before initialization
const c = 3;

3. 重复声明

var: 允许重复声明

var a = 1;
var a = 2; // 合法,a = 2

let/const: 不允许在同一作用域重复声明

let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared

const c = 1;
const c = 2; // SyntaxError: Identifier 'c' has already been declared

4. 初始化要求

var/let: 可以先声明后赋值

var a;
a = 1;

let b;
b = 2;

const: 声明时必须初始化

const c; // SyntaxError: Missing initializer in const declaration
const c = 3; // 正确

5. 全局声明

var: 在全局作用域中声明的变量会成为全局对象(window/global)的属性

var globalVar = "global";
console.log(window.globalVar); // 'global'

let/const: 不会成为全局对象的属性

let globalLet = "not global";
const globalConst = "not global";
console.log(window.globalLet); // undefined
console.log(window.globalConst); // undefined

6. 可修改性

var/let: 声明的变量可以重新赋值

var a = 1;
a = 2; // 合法

let b = 1;
b = 2; // 合法

const: 声明的变量不可重新赋值,但如果值是对象,其属性可以修改

const c = 1;
c = 2; // TypeError: Assignment to constant variable

const obj = { prop: 1 };
obj.prop = 2; // 合法 - 对象属性可以修改
obj = {}; // TypeError: Assignment to constant variable

最佳实践

  1. 默认使用 const:如果一个变量不需要重新赋值,始终使用 const 声明
  2. 需要重新赋值时使用 let:只在确实需要重新赋值的变量上使用 let
  3. 避免使用 var:在现代 JavaScript 中,几乎没有必要使用 var
  4. 在循环中使用 let:特别是在 for 循环中,let 能创建每次迭代的独立变量

延伸问题

  1. let/const/var 三者间的主要区别是什么?
  2. 什么是暂时性死区(Temporal Dead Zone)?
  3. const 声明的对象,为什么其属性可以被修改?
  4. 在什么情况下应该使用 var?
  5. let 和 const 如何影响闭包和循环?