小Dora 的 JavaScript 修炼日记 · Day 1:变量三兄弟与作用域迷宫

"如果连变量都不懂,那你永远也不知道 JavaScript 在发什么疯。"

------ 来自一位在 TDZ 中走丢的程序员

今天是小Dora正式踏入 JavaScript 的第一天,目标明确:未来成为一名高级前端工程师。第一关,就是打通【变量声明】这座看似简单、实则杀机重重的迷宫。


🧭 一、变量三兄弟登场:varletconst

🥷 var ------ 江湖老油条,喜欢走捷径

ini 复制代码
console.log(name); // undefined
var name = "小Dora";

这不会报错,只会输出 undefined,因为 var 有个江湖绝技叫:

变量提升(Hoisting) :变量声明会被"提前"到函数顶部,但赋值不会提升。

就像你抢了考场前排的位置,但忘了带笔,系统只看到你在,但你写不出字。

ini 复制代码
var name;
console.log(name); // undefined
name = "小Dora";

特点总结:

特性 说明
✅ 提升 声明被提升,初始化不被提升
❌ 无块级作用域 {} 对它没用,只认函数作用域
✅ 可重复声明 多次声明互相覆盖也不吭声

🧑‍💼 let ------ 年轻新贵,条条框框一堆

ini 复制代码
console.log(age); // ❌ ReferenceError
let age = 18;

为啥不是 undefined?------因为你误闯了:

⚠️ 暂时性死区 TDZ(Temporary Dead Zone)

所谓 TDZ,就是变量虽然在词法上已经声明了,但在赋值之前你敢碰它,JS 就会直接朝你扔一个 ReferenceError。

javascript 复制代码
{
  // 这里进入 TDZ
  console.log(tool); // ❌ ReferenceError
  let tool = "Vue.js";
  // TDZ 结束
}

let 特性总结:

特性 说明
❌ 无提升 存在 TDZ,不允许提前访问
✅ 块级作用域 出了 {} 就再见了
❌ 不可重复声明 同一作用域声明两次就爆炸

🛡️ const ------ 永不叛变的"铁憨憨"

ini 复制代码
const mission = "成为高级前端";
mission = "成为产品经理"; // ❌ TypeError

你不能改变它指向的值,但是:

ini 复制代码
const config = { debug: true };
config.debug = false; // ✅ 可以改属性

也就是说:你不能换人,但可以给人换衣服。


🧠 二、作用域与生命周期:变量的隐形牢笼

什么是作用域?

作用域 = 变量的"活动范围"

JS 中有三种作用域:

类型 示例 说明
全局作用域 文件最外层定义 到处都能访问
函数作用域 var 定义位置 只在函数内可访问
块级作用域 let/const 定义 花括号 {} 控制访问边界

🧬 生命周期三阶段

每个变量的"人生"都有三个阶段:

阶段 内容说明
创建阶段 引擎发现变量,分配内存
初始化阶段 var 设为 undefinedlet/const 进入 TDZ
执行阶段 正式赋值、参与代码运行

例子:

ini 复制代码
function demo() {
  console.log(a); // undefined
  console.log(b); // ❌ ReferenceError
  var a = 1;
  let b = 2;
}

💻 三、实战演练:作用域对比与 TDZ 演示

1. var 穿墙术

ini 复制代码
{
  var foo = "JS Ninja";
}
console.log(foo); // ✅ JS Ninja

因为 var 无视 {},只有函数能挡住它。


2. let/const 的结界

ini 复制代码
{
  let secret = "封印之术";
}
console.log(secret); // ❌ ReferenceError

let / const{} 外全都"隐身"。


🧪 四、自测问答 · 你能拿满分吗?

✅ 快问快答题(选择题)

1. 以下哪个变量声明不会触发 ReferenceError?

A. let 声明前访问

B. var 声明前访问

C. const 声明前访问

D. 访问未定义变量 x

✅ 答案:B


2. 以下哪种行为不会引发报错?

A. let a = 1; let a = 2;

B. const x = 1; x = 2;

C. const obj = {}; obj.name = 'Dora';

D. let b; console.log(b);

✅ 答案:C


🧠 思维题(简答)

Q1:TDZ 的设计目的是什么?为什么不直接返回 undefined

🎯 答案参考:TDZ 是为了防止访问未初始化的变量。若访问未初始化变量返回 undefined,容易掩盖错误逻辑;TDZ 让错误提早暴露,增强代码健壮性。


Q2:为什么 let 在异步循环中能正确输出索引?

javascript 复制代码
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// 输出:0 1 2

🎯 答案参考:let 在每次循环中创建了独立作用域的 i ,每个 i 都是新的绑定,闭包捕获的是正确的值。


👨‍💻 五、大厂爱问面试题(挑战加深)

💣 面试题 1:以下代码输出什么?

ini 复制代码
function foo() {
  console.log(a); // ?
  console.log(b); // ?
  var a = 10;
  let b = 20;
}
foo();

✅ 输出:

javascript 复制代码
undefined
ReferenceError

💣 面试题 2:

ini 复制代码
{
  var a = 1;
  let b = 2;
}
console.log(a); // ?
console.log(b); // ?

✅ 输出:

javascript 复制代码
1
ReferenceError

💣 面试题 3:

ini 复制代码
const person;
person = { name: "小Dora" };

✅ 输出:SyntaxError: Missing initializer in const declaration


✅ 六、小Dora Day 1 修炼总结

特性对比 var let const
是否提升 ✅ 只提升声明 ❌(存在 TDZ) ❌(存在 TDZ)
作用域类型 函数作用域 块级作用域 块级作用域
可否重复声明 ✅ 可重复 ❌ 报错 ❌ 报错
可否重新赋值 ✅ 可以 ✅ 可以 ❌ 不可重新赋值

🔚 尾声:走出变量迷宫,踏入执行上下文

第一天结束了,小Dora已经理解:

  • 变量三兄弟不仅语法不同,运行机制也不同
  • TDZ、作用域和变量提升,是理解 JS 的起点
  • 每一个变量都有生命周期,控制它就是掌控 JS

📌 下一站:词法作用域、执行上下文与闭包三连击 ------ 这是所有中高级面试绕不过去的必杀技。

如果你也在学习 JavaScript,欢迎继续追更 《小Dora 的 JS 修炼日记》

我们不只写代码,我们要理解代码"为什么这么写"。

相关推荐
gadiaola6 分钟前
【SSM面试篇】Spring、SpringMVC、SpringBoot、Mybatis高频八股汇总
java·spring boot·spring·面试·mybatis
麦兜*1 小时前
Spring Boot 集成Reactive Web 性能优化全栈技术方案,包含底层原理、压测方法论、参数调优
java·前端·spring boot·spring·spring cloud·性能优化·maven
Jinkxs1 小时前
JavaScript性能优化实战技术
开发语言·javascript·性能优化
知了一笑1 小时前
独立开发第二周:构建、执行、规划
java·前端·后端
UI前端开发工作室2 小时前
数字孪生技术为UI前端提供新视角:产品性能的实时模拟与预测
大数据·前端
Sapphire~2 小时前
重学前端004 --- html 表单
前端·html
Maybyy2 小时前
力扣242.有效的字母异位词
java·javascript·leetcode
遇到困难睡大觉哈哈2 小时前
CSS中的Element语法
前端·css
Real_man2 小时前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小彭努力中2 小时前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts