静态作用域是闭包存在的前提,它使JavaScript在函数定义时就确定可访问的外部变量;闭包则是该规则的运行时实现,通过保留定义时的词法环境使内部函数能持续访问父函数变量。

静态作用域是闭包存在的前提,没有静态作用域,就不可能形成真正的闭包。
静态作用域决定变量查找时机
JavaScript 在函数定义时就固定了它能访问哪些外部变量——不是看它在哪里被调用,而是看它写在哪儿。这个“写在哪”的上下文,就是它的词法环境。比如:
- 函数内部引用一个外层变量 x,引擎会沿着定义时的嵌套结构向上找,直到全局作用域
- 即使该函数 later 被传到别的地方执行,甚至作为回调被调用,它依然坚持按原定义位置去找 x
- 这种“认地不认人”的行为,就是静态作用域的体现
闭包是静态作用域的运行时载体
静态作用域只是规则,而闭包是让这条规则落地的具体机制。当一个内部函数被返回或传出时:
- 它会把定义时所在作用域链(包括父函数的变量对象)保存在内部属性 [[Scope]] 中
- 即便父函数执行结束、执行上下文被销毁,这些变量仍保留在内存中,供内部函数持续访问
- 这个“函数 + 它定义时的词法环境”的组合,就是闭包
两者配合解决变量生命周期问题
普通函数执行完,它的局部变量就该释放;但闭包需要这些变量长期存在。静态作用域告诉引擎“该保留谁”,闭包负责实际“留住谁”:
- 如果没有静态作用域,引擎无法预判哪个变量会被后续函数用到,只能按调用时动态决定——那就无法提前保留
- 如果没有闭包机制,静态作用域只是一纸空文:变量查得到,但早被回收了,访问会出错
- 二者缺一不可:静态作用域提供确定性,闭包提供持久性
常见误解澄清
很多人以为“函数里用了外层变量”就叫闭包,其实关键在两点:
- 该函数必须被定义在另一个函数内部(满足词法嵌套)
- 该函数必须在父函数执行结束后,仍然能被访问和调用(触发变量保留)
- 只满足第一条,只是嵌套函数;只有两条都满足,才构成闭包

















