JavaScript变量查找依赖函数定义时固化的作用域链:从当前AO开始就近向上逐级查找VO,直至全局对象;闭包是作用域链因函数被引用而未被回收的自然结果。

JavaScript 中变量查找的底层机制,核心就是作用域链——它不是运行时临时拼凑的路径,而是函数定义时就固化下来的查找路线图。
作用域链在函数定义时就确定了
函数一写出来,它的[[Scope]]内部属性就已经存好了当时所处环境的词法作用域快照。这个快照不会因为函数后来被谁调用、在哪调用而改变。
- 比如全局里定义的函数,它的作用域链只含全局对象
- 在
outer函数里定义的inner,作用域链就包含inner自己的活动对象 →outer的变量对象 → 全局对象 - 哪怕把
inner传给另一个函数执行,这条链也不变
变量查找严格按“就近+向上”顺序进行
每次访问一个标识符(如name),引擎从当前执行上下文的活动对象(AO)开始找;没找到,就跳到作用域链的下一个变量对象(VO);再没找到,继续往上,直到全局对象。一旦找到,立刻停止搜索。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 不跨层跳:不会跳过父级直接去祖父级找
- 不回溯:已经查过的层级不会重复查
- 找不到就报
ReferenceError,而不是undefined
闭包是作用域链“活下来”的自然结果
当一个函数被返回或以其他方式脱离其原始执行上下文后,只要它还在被引用,它所依赖的作用域链就不会被垃圾回收。其中被“捕获”的外部变量,就构成了闭包的数据基础。
-
count能持续累加,是因为inner的作用域链始终保留着对outer中count变量对象的引用 - 没有显式的“闭包语法”,只有词法作用域 + 函数作为值传递 + 引用未释放,三者共同触发
- 这也是为什么用
let/const在循环中创建函数时,每个函数会绑定各自块级作用域里的变量——作用域链不同,捕获的变量实例就不同
调试时可以借助执行上下文和词法环境推演
遇到变量行为异常,别急着查文档,先画出函数定义位置对应的作用域嵌套结构,再标出调用时的执行上下文栈。对照两者,就能判断某个变量该从哪一层取。
- Chrome DevTools 的“Scope”面板会实时显示当前断点处的作用域链
- 用
console.dir(function)能看到[[Scopes]]属性(需开启“Verbose”模式) - 把“函数在哪定义”当成户籍地,“在哪调用”只是出差地——这个类比很管用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










