JavaScript只使用词法作用域,不支持动态作用域;根本区别在于变量查找依据不同:词法作用域看函数“写在哪”,定义时即锁定作用域链,按代码嵌套结构向上查找;动态作用域看函数“在哪被调用”,运行时依调用栈查找,如Bash所示,但JS中不存在。

JavaScript 只使用词法作用域,不支持真正的动态作用域。两者的根本区别在于:变量查找的依据不同——一个看函数“写在哪”,一个看函数“在哪被调用”。
词法作用域:定义时就锁定作用域链
函数的作用域在它被声明(书写)的那一刻就已确定,与后续如何调用无关。引擎按代码嵌套结构构建作用域链,查找变量时逐级向上回溯到外层定义位置。
- 例如:let x = "global"; function bar() { console.log(x); } function foo() { let x = "local"; bar(); } foo(); 输出 "global",因为
bar在全局定义,它的词法环境只包含全局作用域 - 闭包能长期持有外部变量,正是依赖词法作用域的静态绑定特性
- 块级作用域(
let/const)、函数作用域、全局作用域共同构成树状作用域链
动态作用域:调用时才决定变量归属
变量值取决于函数执行时所处的调用栈环境,而非定义位置。当前函数找不到变量,就去“它的调用者”的作用域里找,再往上推,直到全局。
- 这不是 JavaScript 的行为,但可类比 Bash:x=1; foo() { echo $x; }; bar() { local x=2; foo; }; bar 输出 2,因为
foo被bar调用,就继承了bar的局部变量 - 这种机制使代码行为更难预测,调试成本高,现代主流语言基本弃用
- JavaScript 中
this的绑定方式具有动态性,但注意:this不是作用域,也不影响变量查找
为什么 JavaScript 坚持词法作用域
它让变量引用关系在编码阶段就清晰可见,提升可读性、可维护性和工具支持能力(如 IDE 智能提示、静态分析、打包优化)。
立即学习“Java免费学习笔记(深入)”;
- 支持闭包、模块封装、工厂函数等关键模式
- 避免因调用路径变化导致意外的变量覆盖或未定义错误
- 与 ES6+ 的块级作用域、箭头函数、模块系统天然兼容


















