当前位置:首页 > 问答 > 正文

JavaScript 变量声明:js有了var为什么还要有let和const?

JavaScript | 变量声明:js有了var为什么还要有let和const?

场景引入:一个令人抓狂的bug

想象一下这个场景:你正在写一个简单的倒计时功能,代码如下:

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

你期待它输出0,1,2,3,4,但实际上却输出了5个5!这简直让人抓狂,这就是var带来的"惊喜"之一,在ES6之前,JavaScript开发者们不得不忍受这种奇怪行为,直到letconst的出现才解决了这个问题。

var的问题:太"自由"的代价

var在JavaScript中存在已久,但它有几个明显的缺陷:

  1. 函数作用域而非块级作用域var声明的变量在整个函数内都有效,不管它是在哪个代码块中声明的。
function example() {
  if (true) {
    var x = 10;
  }
  console.log(x); // 输出10,x在if块外仍然可访问
}
  1. 变量提升(hoisting)var声明的变量会被提升到函数或全局作用域的顶部。
console.log(y); // 输出undefined而不是报错
var y = 5;
  1. 允许重复声明:同一个作用域内可以多次声明同一个变量而不报错。
var z = 1;
var z = 2; // 不会报错
console.log(z); // 输出2

这些特性经常导致难以追踪的bug,尤其是在复杂的代码中。

JavaScript 变量声明:js有了var为什么还要有let和const?

let和const的救赎

ES6(ES2015)引入了letconst,它们解决了var的大部分问题:

let:块级作用域的变量

function example() {
  if (true) {
    let x = 10;
    console.log(x); // 输出10
  }
  console.log(x); // 报错:x未定义
}

let的特点:

  • 块级作用域:只在声明它的代码块内有效
  • 不存在变量提升:在声明前访问会报错
  • 不允许重复声明:同一作用域内不能重复声明同一变量
console.log(a); // 报错:Cannot access 'a' before initialization
let a = 5;
let b = 1;
let b = 2; // 报错:Identifier 'b' has already been declared

const:不可变的常量

const除了具有let的所有特性外,还有额外限制:

JavaScript 变量声明:js有了var为什么还要有let和const?

  • 声明时必须初始化
  • 不能重新赋值(但对于对象和数组,内容可以修改)
const PI = 3.14159;
PI = 3; // 报错:Assignment to constant variable
const arr = [1, 2, 3];
arr.push(4); // 允许,因为数组内容可以修改
arr = []; // 报错:Assignment to constant variable

为什么需要三者共存?

既然letconst这么好,为什么还要保留var呢?主要原因包括:

  1. 向后兼容:大量旧代码使用var,直接移除会导致很多网站崩溃
  2. 特殊用途:在某些情况下,var的函数作用域特性可能正是你需要的
  3. 全局变量:在全局作用域中,varlet的行为略有不同

现代JavaScript的最佳实践

根据2025年的最新实践,推荐以下变量声明方式:

  1. 默认使用const:除非你知道变量需要重新赋值,否则优先使用const
  2. 需要重新赋值时用let:当变量需要在代码中改变时使用let
  3. 避免使用var:除非你有特殊需求或维护旧代码,否则不要使用var
// 好的实践
const MAX_SIZE = 100; // 不会改变的常量
let count = 0; // 需要递增的计数器
// 不好的实践
var oldWay = "avoid this"; // 除非必要

letconst的引入解决了var带来的许多问题,使JavaScript更接近其他现代编程语言的变量声明方式,它们提供了更严格的块级作用域、更可预测的行为,并帮助开发者避免常见错误,虽然var仍然存在,但在新代码中,constlet应该是你的首选。

JavaScript 变量声明:js有了var为什么还要有let和const?

默认用const,需要改变用let,避免使用var,这样你的代码会更清晰、更少bug,也更容易维护。

发表评论