作用域与执行上下文
区分词法作用域与执行上下文,解释作用域链如何查找变量,并为闭包与提升打地基。
#type / concept
#status / growing
#tech / dev
#resource / javascript
#resource / ecmascript
[!info] 关联笔记
- 所属:语言基础 MOC
- 后续:闭包 · 执行上下文 · 变量提升 · var/let/const
作用域与执行上下文
这个概念为什么出现
“变量从哪来/为什么读到旧值/为什么 TDZ 报错”都混在口语“作用域”里。拆开后:
- 作用域:写代码结构决定的可见性规则(词法)
- 执行上下文:运行到某段代码时创建的运行环境
[!abstract] 一句话理解 作用域是编译/解析期定下的查词地图;执行上下文是运行时沿着地图真正找值的现场。
最小可运行示例
场景:折扣函数里的仓库税率
const warehouseTax = 0.03 // 全局词法环境
function priceWithTax(base) {
const serviceFee = 2 // 函数作用域
function finalize(total) {
// 教学点:finalize 词法上能看见 serviceFee 与 warehouseTax
return total + serviceFee + total * warehouseTax
}
return finalize(base)
}
console.log(priceWithTax(100))
期望:100 + 2 + 3 = 105。
再看块级:
function demo() {
if (true) {
let flag = 'inside'
}
// console.log(flag) // ReferenceError:块级作用域
}
核心模型
作用域类型
- 全局
- 函数
- 块(
let/const/class等) - 模块作用域
作用域链
内部函数查找标识符:自己环境 → 外层词法环境 → … → 全局。这是闭包的地基。
执行上下文包含(教学)
- 词法环境 / 变量环境
- 外部引用(链)
this绑定(函数上下文)
每次函数调用创建新的执行上下文,压入调用栈。
与提升关系
var 函数作用域 + 提升;let/const 暂时性死区。详见 变量提升。
常见误区
[!warning] 常见误区:作用域 = this this 是绑定规则;作用域是标识符解析。
本节总结
先分清“地图(作用域)”与“在地图上跑的一次调用(执行上下文)”,闭包与提升才不会玄学。
自测题
- 为什么内层函数能读外层
const? - 每次调用函数是否共享同一执行上下文?
参考答案
- 词法作用域链在定义时确定外层引用。
- 不共享;每次调用创建新上下文(闭包保留的是环境引用,不是单次栈帧本身的简单复用叙事)。