嵌套函数的作用域链在定义时静态绑定,由[[scope]]属性保存词法环境快照,执行时按“内→外→全局”顺序查找变量,且闭包由此自然产生。

嵌套函数形成作用域链,核心在于函数定义时就“记住”了它所处的词法环境,而不是执行时才决定。这种静态绑定机制让内部函数能逐层向上访问外部函数和全局作用域中的变量。
函数嵌套定义即刻建立作用域链
作用域链在函数被创建(定义)的那一刻就已确定,与是否调用无关。每个函数内部都隐含一个 [[Scope]] 内部属性,保存着它定义时所在作用域链的快照。
- 外层函数定义时,其 [[Scope]] 指向全局作用域
- 内层函数定义在该外层函数内部,它的 [[Scope]] 就包含:自身外层函数的作用域 + 外层函数的 [[Scope]](即全局作用域)
- 因此,作用域链天然呈“内→外→全局”的嵌套结构
执行时沿链查找变量
当嵌套函数执行,JavaScript 引擎会创建执行上下文,并基于函数定义时的 [[Scope]] 构建当前作用域链。变量查找严格按此链顺序进行:
- 先查当前函数自身的变量对象(含参数、let/const/var 声明)
- 没找到,就去外层函数的作用域中找
- 仍没找到,继续向上,直到全局作用域
- 全程未命中且为严格模式 → ReferenceError;非严格模式读取未声明变量 → undefined
词法作用域是根本依据
作用域链依赖的是代码书写时的嵌套结构,而非调用位置。即使把内层函数作为返回值传到别处执行,它依然沿用定义时的链:
例如:function outer() {<br> const x = 10;<br> return function inner() { console.log(x); };<br>}<br>const fn = outer();<br>fn(); // 仍能输出 10 —— 因为 inner 定义时就绑定了 outer 的作用域
闭包是作用域链的自然结果
当嵌套函数在外部被调用,且引用了外层函数的变量,这个变量就不会被垃圾回收——因为作用域链仍在维持对其的引用。这就是闭包的底层原理:
- 没有显式返回内部函数,外层函数执行完后其作用域通常被释放
- 一旦内部函数被保留(如赋值给变量、作为回调),它携带的作用域链会持续持有对外层变量的引用
- 多个内部函数可共享同一外层作用域,形成数据隔离又协同的封闭环境
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











