javascript只使用词法作用域,不支持原生动态作用域;变量查找在函数定义时就依据代码嵌套结构确定,而非调用时的执行栈。

JavaScript 只使用词法作用域,不支持原生动态作用域。所谓“区别执行逻辑”,本质是看变量查找发生在哪个阶段、依据什么结构。
变量查找时机不同
词法作用域的查找路径在函数定义时就固定了,和它将来在哪被调用无关;动态作用域则推迟到函数实际执行那一刻,沿着调用栈向上找最近的同名变量。
- 词法作用域:编译阶段(代码写完、还没运行)就确定了每个函数能访问哪些外层变量
- 动态作用域:运行阶段,每次调用函数时都重新根据调用链决定从哪一层取变量
查找依据的结构不同
词法作用域依赖代码的嵌套书写位置,像一层层套娃的代码块;动态作用域依赖函数调用的先后顺序,像一条向上的调用链条。
- 函数内部引用 x,词法作用域会检查它定义时外层有没有 x(比如父函数或全局)
- 同样引用 x,动态作用域会检查“谁调用了我”,然后去那个调用者的局部作用域里找 x
典型行为对比示例
下面这段 JavaScript:
var value = 1;
function foo() { console.log(value); }
function bar() { var value = 2; foo(); }
bar(); // 输出 1
输出是 1,因为 foo 定义在全局,它词法上只认全局的 value;即使 bar 内部有同名变量且调用了 foo,也影响不了查找结果。
如果这是动态作用域语言(如 Bash),同一段逻辑会输出 2——因为 foo 被 bar 调用,就去 bar 的作用域里找 value。
JavaScript 中没有真正的动态作用域
虽然 eval() 和 with 语句能在运行时临时改变作用域链,但它们已被严格限制、不推荐使用,也不代表语言本身支持动态作用域。
- eval("console.log(x)") 在哪里执行,就尝试访问哪里的作用域(看似动态,实为特殊机制)
- with(obj) 会把对象属性临时注入当前作用域,但 ES5 严格模式已禁用,现代代码应避免
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











