> 技术文档 > JavaScript:var、let和const的区别_js var let const的区别

JavaScript:var、let和const的区别_js var let const的区别

在 JavaScript 中,变量声明主要有三种关键字:var, let, 和 const。它们各有不同的作用域、提升行为和赋值限制。以下是详细对比:


📌 1. var (传统变量声明)

特点:
  • 函数作用域:在整个函数内部有效
  • 变量提升:声明会被提升到作用域顶部,但赋值不会
  • 可重复声明:同一作用域内允许重复声明
  • 可修改:声明后可以重新赋值
  • 全局属性:在全局作用域声明的变量会成为 window 对象的属性
console.log(a); // undefined (变量提升)var a = 10; var a = 20; // 允许重复声明function test() { var b = \"scope\";}console.log(b); // ReferenceError (函数作用域限制)

🚫 2. let (ES6块级变量声明)

特点:
  • 块级作用域:只在 {} 代码块内有效
  • 暂时性死区 (TDZ):声明前访问会报错
  • 禁止重复声明:同一作用域内不可重复声明
  • 可修改:声明后可以重新赋值
console.log(x); // ReferenceError (TDZ)let x = 5;{ let y = \"block\";}console.log(y); // ReferenceErrorlet z = 10;let z = 20; // SyntaxError (禁止重复声明)

🔒 3. const (ES6常量声明)

特点:
  • 块级作用域:同 let
  • 初始化必赋值:声明时必须赋值
  • 禁止重复声明/赋值:不可重新赋值
  • 引用类型内容可变:对象/数组内部值可修改(指针不变)
  • 暂时性死区:同 let
const PI = 3.14;PI = 3; // TypeErrorconst obj = { name: \"John\" };obj.name = \"Anna\"; // ✅ 允许修改属性const arr = [1, 2];arr.push(3); // ✅ 修改数组内容

🔍 关键区别汇总

特性 var let const 作用域 函数级 块级 块级 变量提升 ✅ (值为undefined) ❌ (存在TDZ) ❌ (存在TDZ) 重复声明 ✅ ❌ ❌ 重新赋值 ✅ ✅ ❌ 初始化要求 ❌ ❌ ✅ (必须立即赋值) 全局对象属性 ✅ ❌ ❌ 循环中表现 常见闭包问题 每次迭代新绑定 同 let

🎯 使用建议

场景 推荐关键字 基本常量 (数字/字符串等) const 循环变量 let 需要重新赋值的变量 let 遗留代码/特殊情况 var

黄金法则:优先使用 const → 需要重新赋值时用 let → 避免使用 var


⚠️ 常见误区

// 陷阱1:const 的对象属性可变const user = { name: \"Alice\" };user.name = \"Bob\"; // ✅ 允许// 陷阱2:for 循环中 var 的行为for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // 输出 3,3,3}// 解决:改用 letfor (let j = 0; j < 3; j++) { setTimeout(() => console.log(j), 100); // 输出 0,1,2}

掌握这三种声明方式的差异,能够帮助您编写更安全、可预测的 JavaScript 代码!🏆


在 JavaScript 中,除了常见的 varletconst 之外,还有以下几种变量声明和值绑定方式:

1. 全局变量声明(不推荐)

  • 不使用任何关键字声明
  • 在非严格模式下直接赋值创建全局变量
  • 这是最不安全的声明方式(容易造成变量污染)
noKeywordVariable = 42; // 自动成为全局对象的属性(浏览器中是 window)console.log(noKeywordVariable); // 42console.log(window.noKeywordVariable); // 浏览器中输出 42

2. 函数参数声明

  • 函数参数本身就是局部变量声明
  • 行为类似 var(在 ES5 及之前)或 let(在 ES6 严格模式)
function example(a, b) { a = 5; // 可以重新赋值 console.log(a); // 5}

3. function 声明(函数声明)

  • 使用 function 关键字声明函数
  • 具有提升行为(可在声明前调用)
myFunction(); // 正常工作(函数声明提升)function myFunction() { console.log(\"Hello!\");}

4. class 声明(ES6+)

  • 创建类构造函数
  • 类似 let 的块级作用域(但有提升限制)
class MyClass { // 类定义}const instance = new MyClass();

5. import 声明(ES6 模块)

  • 导入模块绑定
  • 行为类似 const(不可重新赋值)
// 在模块中import { someExport } from \'./module.js\';import * as utils from \'./utilities.js\';

6. export 声明(ES6 模块)

  • 导出变量绑定
  • 不是传统声明方式,但创造了可导出的绑定
// 在模块中export const apiKey = \'123-ABC\';export function getData() { ... }

7. 解构赋值声明

  • 不是独立的声明方式,但结合其他关键字使用
  • 可一次性声明多个变量
// 对象解构const { name, age } = person;// 数组解构const [first, second] = items;

8. try...catch 中的 catch 参数

  • catch 块中的错误参数创建块级作用域变量
try { throw new Error(\"Test\");} catch (err) { // err 变量只在此块内有效 console.log(err.message);}

9. 函数表达式赋值

  • 使用函数表达式而非函数声明
  • 绑定到变量名上
const myFunction = function() { console.log(\"Function expression\");};

总结比较表

声明方式 作用域 提升行为 重新赋值 使用场景 var 函数作用域 ✅ ✅ 遗留代码 let 块作用域 ❌ ✅ 可变变量 const 块作用域 ❌ ❌ 常量引用 无关键字 全局 提升 ✅ 避免使用 函数声明 块作用域 ✅ ✅ 函数定义 类声明 块作用域 ❌ ❌ 类定义 import 模块作用域 ✅ ❌ 模块导入 解构赋值 依赖绑定 ❌ 依赖绑定 批量赋值

在实践中,建议:

  1. 优先使用 const 声明
  2. 需要重新赋值时用 let
  3. 避免使用 var 和无关键字声明
  4. 使用模块导入导出管理跨文件变量
  5. 利用解构赋值简化声明过程

这些不同的声明方式共同构成了 JavaScript 灵活但需要谨慎使用的变量系统。