从零学 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,更能写出更清晰、更安全的代码。

相关推荐
gustt4 小时前
JS 变量那些坑:从 var 到 let/const 的终极解密
前端·javascript
十年_H4 小时前
Cesium自定义着色器-模式
javascript·cesium
shuaijie05184 小时前
表格单元格输入框转换-其一
javascript·elementui
Z_B_L4 小时前
问题记录--elementui中el-form初始化表单resetFields()方法使用时出现的问题
前端·javascript·vue.js·elementui·1024程序员节
柳鲲鹏4 小时前
多种方法:OpenCV中修改像素RGB值
前端·javascript·opencv·1024程序员节
爱怪笑的小杰杰5 小时前
Cesium中的倒立四棱锥:从几何结构到交互式3D可视化
javascript·3d·arcgis·1024程序员节
不会算法的小灰5 小时前
JavaScript基础详解
开发语言·javascript·udp
十一吖i10 小时前
vue3表格显示隐藏列全屏拖动功能
前端·javascript·vue.js
徐同保11 小时前
tailwindcss暗色主题切换
开发语言·前端·javascript