🧠 第一章:作用域链快递员

- 快递小哥送包裹(变量)的3种路径
- 当前作用域(楼道快递柜)
- 外部作用域(小区公告栏)
- 全局作用域(城市快递中心)
📦 示例1.js演示:快递小哥的迷路之旅
javascript
function bar() {
console.log(myName); // 小哥在楼道没找到包裹
}
function foo() {
var myName = "极客";
console.log(myName); // 小哥在楼道顺利签收
}
var myName = "骑士"; // 全局快递中心存了"骑士"
foo(); // 小哥先查楼道再查公告栏

💥 漫画对话 :
快递员:"楼道快递柜空空如也!"
公告栏:"我这里有'骑士',但小哥你跑错地方啦!"
🎒 第二章:闭包背包工厂

- 背包打包三部曲:
- 创建时:装进行李(变量声明)
- 运输中:保护行李(内存保留)
- 使用时:精准取物(自由变量访问)
🎭 示例3.js演示:背包客的奇幻漂流
javascript
function foo() {
var myName = "极客时间"
let test1 = 1
return {
getName: function(){ return myName } // 背包装入"极客时间"
}
}
var bar = foo()
console.log(bar.getName()) // 背包客掏出记忆中的行李
🎭 三幕剧:
- 打包:小明把"极客时间"塞进帆布包
- 运输:背包穿越地铁站(函数执行结束)
- 取物:小明在咖啡馆掏出包里的"极客时间"
🔄 第三章:执行上下文剧院

- 函数入场五幕剧:
- 票务系统(参数预处理)
- 检票口(变量提升)
- 剧场灯光(TDZ警戒)
- 演员登场(代码执行)
- 幕后整理(作用域回收)
🎭 示例2.js演示:剧院里的变量纠纷
javascript
function bar() {
var myName = "极客世界" // var演员提前入场
let test1 = 100 // let演员迟到(TDZ警戒)
if (1) {
let myName = "Chrome浏览器" // 剧场新增临时座位
console.log(test) // 💣TDZ雷区:test演员还没换衣服
}
}

🚨 TDZ表情包 :
let test
是个害羞的演员,开灯前(代码执行前)不能偷看TA的戏服!
🧩 第四章:词法作用域谜题

-
动态vs静态作用域:快递单编号之谜
javascriptfunction outer() { var name = "A" return function inner() { console.log(name) // 为什么永远是"A"? } } var fn = outer() var name = "B" fn() // 静态作用域:快递单写死"A",动态作用域会变成"B"!

🧩 对比表格:var/let/const的性格差异
特性 | var(老顽固) | let/const(新贵) |
---|---|---|
变量提升 | ✅ 穿越时空 | ❌ 严格检票 |
块级作用域 | ❌ 混乱全场 | ✅ 独立包厢 |
TDZ | ❌ 无预警 | ✅ 警戒线🚨 |
🧠 记忆口诀 & 互动测试
作用域三不原则:
- 不问调用位置(只看代码结构)
- 不跨函数查找(函数是作用域墙)
- 不忘TDZ雷区(let/const有警戒期)
🧪 选择题:
javascript
function mystery() {
console.log(a); // 输出?
var a = 3;
if (true) {
let a = 4;
console.log(a);
}
}
mystery();
💡 答案弹窗 :
undefined
(变量提升) → 4
(块级作用域)
🧠 彩蛋:var a就像没穿衣服的演员,先入场后换装!
🎉 思考题 & 彩蛋
-
为什么闭包被称为"时间胶囊"?
🧨 答案:它冻结了函数创建时的变量状态!
-
如何用TDZ解释"快递签收前不能拆箱"?
🧨 答案:let/const的变量在声明前就像未签收的快递,禁止查看!
-
执行上下文的"检票口"和"剧场灯光"分别对应什么技术概念?
🧨 答案:变量提升(var)和TDZ(let/const)!
🧠 技术总结
✨ 核心公式 :
作用域链 = 快递员路径
闭包 = 背包工厂 + 时间胶囊
执行上下文 = 剧院五幕剧
🎯 终极目标 :
让每个菜鸟都能笑着写出:
javascript
function createCounter() {
let count = 0;
return () => count++;
}
😄 彩蛋:闭包就像恋爱关系------永远记得对方的变量!