函数声明在局部作用域中天然构建闭包,固化对外层变量的引用,使变量在外部函数执行完毕后仍保留在内存中;其词法环境通过[[environment]]属性绑定,作用域链逐级向上链接,且闭包形成取决于声明位置而非调用时机。

函数声明在局部作用域中构建闭包时,核心表现是:它让内部函数“固化”对外层变量的引用,即使外层函数已执行完毕,这些变量仍保留在内存中并可被持续访问。
函数声明天然支持闭包形成
用 function 关键字声明的函数,在定义时就绑定其词法环境。只要它引用了外层作用域的变量,并被返回或传递到外部作用域,闭包就自动成立。
- 不需要额外语法(如箭头函数或立即执行),声明即捕获环境
- 函数名在作用域内可见,便于递归调用或调试追踪
- V8 引擎为该函数创建 [[Environment]] 内部属性,指向声明时的 Lexical Environment
局部作用域变量不会因外层函数退出而销毁
当函数声明位于另一个函数内部,且该内部函数被返回或赋值给外部变量,外层函数的局部变量(let/const/var 声明)将被“延长生命周期”。
- var 变量会提升并绑定到函数级作用域,闭包访问的是同一变量绑定
- let/const 变量虽不提升,但闭包仍能准确访问其块级绑定(V8 为每个块创建独立环境记录)
- 注意:若内部函数未引用某局部变量,V8 GC 可能优化释放——闭包只保留“被引用”的变量
结构上体现为嵌套执行上下文链
每次调用外层函数,都会生成新的执行上下文;其中声明的内部函数,每个实例都携带专属的作用域链。
- 作用域链顶端是内部函数自身变量对象
- 下一层指向外层函数的词法环境(含其局部变量)
- 再向上链接至全局环境,形成可逐级查找的链表结构
- Chrome DevTools 的 Scope 面板可直观查看 Closure 子树
常见误判点:声明位置决定闭包能力,而非调用时机
闭包是否产生,取决于函数**在哪里被声明**,而不是在哪里被调用。
- 即使把内部函数作为参数传入 setTimeout 或事件回调,只要声明在局部作用域内,就构成闭包
- 若函数在全局声明,即使内部访问了局部变量(不可能),也不会形成闭包——因为无外层局部环境可捕获
- 重复调用外层函数,会生成多个独立闭包,各自维护一份外层变量副本
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











