从零学 JavaScript:彻底搞懂 var、let、const(上篇)——告别变量提升的坑

前言:为什么你必须重新理解 JavaScript 的变量声明?

你是否曾遇到过这样的困惑?

js 复制代码
console.log(age); // 输出 undefined,而不是报错?
var age = 18;

console.log(height); // 直接报错!
let height = 1.88;

明明都是声明变量,为什么 varlet 的行为完全不同?

为什么 const 声明的"常量"对象,属性还能改?

如果你也曾被这些问题困扰,那么恭喜你,你即将揭开 JavaScript 中最经典、最易错的一块拼图:varletconst 的本质区别


一、早期 JavaScript:var 的"糟粕"时代

在 ES6(2015 年)之前,JavaScript 只有一个关键字来声明变量:var

js 复制代码
var age = 18;

var 的设计存在严重问题,最典型的就是 变量提升(Hoisting)

什么是变量提升?

JavaScript 的执行分为两个阶段:

  1. 编译阶段 :检查语法,提升 var 和函数声明
  2. 执行阶段:逐行执行代码

var 声明的变量会在编译阶段就被提升到作用域顶部,但赋值仍然留在原地。

实例说明:

js 复制代码
console.log(age); // 输出:undefined
var age = 18;
console.log(age); // 输出:18

这段代码的实际执行过程是:

js 复制代码
// 编译阶段:var age 被提升
var age; // 此时 age = undefined

// 执行阶段:
console.log(age); // undefined
age = 18;
console.log(age); // 18

这种行为完全违背直觉:还没声明就能访问,但值却是 undefined


⚠️ 二、var 的三大"坏味道"

1. 变量提升导致逻辑混乱

js 复制代码
function example() {
  console.log(a); // undefined
  var a = 10;
}

你本意是先声明再使用,但 JavaScript 却允许你在声明前访问,只是值为 undefined。这极易导致 bug。

2. 不支持块级作用域

js 复制代码
if (true) {
  var age = 18;
}
console.log(age); // 18!竟然能访问到

iffor 等块级作用域中声明的 var 变量,会泄露到外部作用域。这在大型项目中非常危险。

3. 没有常量的概念

js 复制代码
var PI = 3.1415926;
PI = 3.14; // 竟然可以修改!

虽然开发者约定"大写字母命名表示常量",但 JavaScript 本身不强制,容易被误改。


三、ES6 的救赎:letconst

2015 年,ES6 正式发布,带来了 letconst,彻底解决了 var 的问题。

let:现代变量声明的首选

js 复制代码
let height = 1.88;
height++; // 可以修改

let 的特点:

  • 不提升:不能在声明前访问
  • 支持块级作用域 :只在 {} 内有效
  • 不允许重复声明

实例对比:

js 复制代码
// var 的问题
console.log(age); // undefined
var age = 18;

// let 的正确行为
console.log(height); // 报错!Cannot access 'height' before initialization
let height = 1.88;

const:真正的常量

js 复制代码
const PI = 3.1415926;
PI = 3.14; // 报错!Assignment to constant variable.

const 声明的变量一旦赋值就不能再修改 ,否则会抛出 TypeError

注意:const 保证的是引用地址不变,而不是值不可变。


四、常见的错误与报错解析

1. ReferenceError: height is not defined

js 复制代码
console.log(height); // 报错

原因:变量 height 根本不存在,或在作用域外访问。

2. TypeError: Assignment to constant variable.

js 复制代码
const PI = 3.14;
PI = 3.15; // 报错

原因:尝试修改 const 声明的变量。

3. ReferenceError: Cannot access 'PI' before initialization

js 复制代码
console.log(PI);
const PI = 3.14; // 报错

原因:constlet 存在暂时性死区(Temporal Dead Zone),不能在声明前访问。


五、暂时性死区:letconst 的安全机制

"暂时性死区"听起来很玄乎,其实很简单:

从进入作用域到变量声明完成之前,该变量都不可访问。

示例:

js 复制代码
{
  console.log(a); // 报错!TDZ
  let a = 10;
}

这与 var 的"提升但值为 undefined"完全不同,它强制你先声明再使用,提高了代码的可读性和安全性。


六、最佳实践建议

场景 推荐使用
普通变量 let
不会重新赋值的变量 const
不再使用 var

建议:从今天起,彻底告别 var,全面使用 letconst


JavaScript 正在变得越来越"严谨"

var 是 JavaScript 早期设计不完善的产物,而 letconst 的出现,标志着 JavaScript 正在向更严谨、更适合大型项目开发的语言演进。

理解它们的区别,不仅能避免常见 bug,更能写出更清晰、更安全的代码。

相关推荐
作业逆流成河3 分钟前
别再一次性重构枚举了:如何把一个真实后台项目的状态字典,渐进式迁移到enum-plus?
前端·javascript·开源
ct97844 分钟前
TypeScript 中的泛型
前端·javascript·typescript
qq_420362031 小时前
前端国际化方案
前端·javascript·vue.js·国际化·reactjs
向上的车轮1 小时前
React 19 快速入门:拥抱服务端组件与新特性的现代化开发
前端·javascript·react.js
Smile_2542204181 小时前
vue3 + ts reactive方式清空表单对象
开发语言·前端·javascript
ZC跨境爬虫2 小时前
跟着 MDN 学CSS day_31:(精通链接样式,从伪类到导航菜单)
前端·javascript·css·ui·交互
香香爱编程2 小时前
vue3自定义顶部弹窗
前端·javascript·vue.js
蜡台2 小时前
Vue Echart 的 **高阶组件化** 封装思路
前端·javascript·vue.js·echarts
xuankuxiaoyao2 小时前
vue.js 路由第二篇
前端·javascript·vue.js
开开心心就好2 小时前
解决图片无页码添加功能的实用工具
javascript·python·安全·智能手机·pdf·音视频·1024程序员节