← JavaScript const 常量声明 JavaScript条件判断语句if else →

JavaScript变量var、let和const

原创 2026-03-12 JavaScript 已有人查阅

JavaScript 变量声明:var、let 和 const 的区别与选择

今天咱们来聊聊 JavaScript 里最基础但也最容易踩坑的话题——变量声明。不论你是刚入门的新手,还是写了几年代码的老手,varlet 和 const 这三个关键字绝对是绕不开的核心概念。

很多同学刚开始学的时候,会觉得“不就是声明个变量嘛,用哪个不都一样?” 但实际上,它们背后的作用域(Scope)提升(Hoisting) 以及重新赋值(Reassignment) 的规则天差地别。如果不搞清楚,代码里出现一些莫名妙的 bug 都不知道去哪找。

接下来,我就结合我这些年写代码的经验,帮你把这几个概念掰扯明白。

一、初识三兄弟:var, let, const

变量就是一个存放数据的“容器”。在 JavaScript 里,我们通过 varlet 和 const 来创建这些容器。它们就像三兄弟,长得像,但脾气秉性不同。

  • var:这是 JavaScript 里的“老大哥”,从语言诞生之初就存在。它的作用域是函数级的,比较“粗犷”,容易出问题。

  • let:这是 ES6(ECMAScript 2015)引入的“新派代表”,用来解决 var 的一些遗留问题。它的作用域是块级的,更精细、更安全。

  • const:和 let 一样是“新派代表”,也是块级作用域。但它有个鲜明的特点:常量。一旦赋值,就不能再改变指向。

二、怎么用?看看它们的性格

光说不练假把式,咱们直接上代码,看看它们分别是怎么工作的。

1. var 的声明:函数级作用域

var 声明的变量,要么是全局的,要么是整个函数的。它不太“认” {}(花括号)这个界限。

// 在代码号学习 var
function learnVar() {
    if (true) {
        var message = "这是 var 声明的变量";
        console.log(message); // 输出:这是 var 声明的变量
    }
    // 注意!在 if 语句外面,依然可以访问 message
    console.log(message); // 输出:这是 var 声明的变量(没问题,因为 var 是函数级的)
}
learnVar();
// 在函数外部访问?不行,因为它是函数作用域
// console.log(message); // 报错:message is not defined

个人经验: 在实际开发中,我已经很少用 var 了。因为它太“自由”,很容易不小心就在同一个函数里重复声明同一个变量,导致后面的值把前面的覆盖掉,而且没有错误提示,排查起来很头疼。

2. let 的声明:块级作用域

let 的出现,就是为了解决 var 作用域不精确的问题。它只认 {} 这个“块”。

// 在代码号学习 let
function learnLet() {
    if (true) {
        let grade = "A+";
        console.log(grade); // 输出:A+
    }
    // 这里就访问不到了,因为 grade 只在 if 语句块里有效
    // console.log(grade); // 报错:grade is not defined
}
learnLet();

看到区别了吗?用 let 声明,变量就被牢牢地锁在了它所在的代码块里,这能有效避免很多变量污染的问题。

3. const 的声明:不变的承诺

const 用来声明一个只读的常量。一旦声明,它的值(或者说引用)就不能改变。而且声明的时候就必须赋值,不能只写个名字放那。

// 在代码号学习 const
const SITE_NAME = "代码号";
console.log(SITE_NAME); // 输出:代码号

// SITE_NAME = "易编程"; // 报错:Assignment to constant variable. (常量不允许重新赋值)

const USER = { name: "老杨", age: 18 };
USER.age = 19; // 这却可以!因为 USER 指向的对象没变,只是改了对象里面的属性
console.log(USER); // 输出:{ name: "老杨", age: 19 }

// USER = { name: "老杨", age: 20 }; // 报错:这是重新赋值一个新的对象,不允许

关键点: const 保证的不是变量的值不能变,而是变量指向的那个内存地址不能变。对于基本类型(数字、字符串、布尔值),值就保存在那个地址里,所以值不能变。对于引用类型(对象、数组),地址里保存的只是一个指针,只要指针不变,修改对象内部的属性是允许的。

三、核心区别大比拼

为了让你看得更清楚,我把它们的核心区别整理成了一张表,这也是面试中经常被问到的知识点。

特性 var let const
作用域 函数级作用域 / 全局作用域 块级作用域 ({}内) 块级作用域 ({}内)
重复声明 允许在同一个作用域重复声明 不允许在同一个作用域重复声明 不允许在同一个作用域重复声明
重新赋值 允许 允许 不允许
声明前访问 可以访问,值为 undefined (提升) 报错 ReferenceError (存在暂存死区) 报错 ReferenceError (存在暂存死区)
必须初始化 否 (可以不赋值,默认为 undefined 否 (可以不赋值,默认为 undefined  (声明时必须赋值)

个人见解: 现在的前端项目(无论是 Vue 还是 React 项目),几乎都是全面拥抱 ES6+ 语法。我的建议是,默认用 const,只有在确定变量的值后面需要改变时,才用 let 至于 var,除非你在维护一些非常古老的代码,否则就让它“退休”吧。这样做的好处是,代码的逻辑意图会更清晰,别人看到 const 就知道这个变量不会变,减少心智负担。

四、深入理解:提升(Hoisting)与暂存死区

“提升”是 JavaScript 里一个比较绕的概念,但理解了它,你就能明白为什么 var 和 let 的行为如此不同。

1. var 的提升:只有“名”被提升了

JavaScript 引擎在解释执行代码之前,会先有一个“编译”阶段。这个阶段会把所有用 var 声明的变量,“提升”到它所在作用域的顶部,但只提升声明,不提升赋值。

console.log(myVar); // 输出:undefined (而不是报错!)
var myVar = 10;
console.log(myVar); // 输出:10

// 上面的代码,JavaScript 引擎实际理解的是这样:
// var myVar; // 声明被提升到这里了
// console.log(myVar); // 此时 myVar 已声明,但未赋值,所以是 undefined
// myVar = 10; // 赋值还在原地
// console.log(myVar);

这就是为什么用 var 能在声明前访问到变量,但值是 undefined

2. let 和 const 的提升:在“暂存死区”里寸步难行

很多资料说 let 和 const 不会提升,这个说法实不严谨。更准确的说法是:它们也会被提升,但提升后的行为不一样。

从进入作用域开始,到变量真正声明的位置,这中间的区域就叫“暂存死区”。在这个区域内,你不能访问该变量,一旦访问,JavaScript 引擎就会毫不留情地抛出一个 ReferenceError

// console.log(myLet); // 报错:ReferenceError: Cannot access 'myLet' before initialization
let myLet = 20;
console.log(myLet); // 输出:20

这实是一种更合理的设计。它强制你必须先声明后使用,避免了 var 那种产生意外 undefined 的情况。

五、课后总结与建议

我们来总结一下这三个声明的核心要点:

  1. var:函数作用域,允许重复声明,会提升并初始化为 undefined特点:灵活但容易出bug。

  2. let:块级作用域,不允许重复声明,会提升但存在“暂存死区”,声明前访问会报错。特点:精确控制,是 var 的现代替代品。

  3. const:拥有 let 的所有特点(块级、不重复声明、暂存死区),额外声明时必须赋值,且不能重新赋值(对于引用类型,引用不可变,但属性可变)。特点:语义明确,用于定义常量。

希望今天这篇内容,能帮你把这三个关键字彻底理清。下次写代码的时候,可以多想想,你这个变量应该是 const 还是 let?如果想不明白,就优先用 const,直到编译器报错说“你需要重新赋值”的时候,再改成 let。这是个不错的实践习惯。

← JavaScript const 常量声明 JavaScript条件判断语句if else →
分享笔记 (共有 篇笔记)
验证码:
微信公众号