javascript采用词法作用域,函数作用域、块级作用域均为其具体体现;变量查找路径由定义位置静态决定,与调用位置无关,闭包和变量提升均源于此规则。

JavaScript 中没有“函数作用域 vs 词法作用域”这种对立关系——函数作用域是词法作用域的一种具体体现,不是并列或互斥的概念。真正需要区分的是词法作用域(Lexical Scoping)和动态作用域(Dynamic Scoping),而 JavaScript 全面采用前者。
词法作用域:函数定义时就锁定查找路径
词法作用域指函数能访问哪些变量,完全取决于它在源代码中**定义的位置**,而不是在哪里被调用。
- 嵌套函数自动捕获其外层函数(及全局)中定义的变量,形成静态可追溯的作用域链
- 即使外层函数已执行完毕,内层函数仍能通过闭包访问那些变量
- 编译阶段就能确定变量从哪一层作用域开始查找,不依赖运行时调用栈
所谓“函数作用域”其实是词法作用域下的行为模式
使用 var 声明的变量具有函数作用域,这是词法作用域规则在函数层级上的自然结果:
-
var变量绑定到最近的函数作用域(而非块),这个“最近的函数”由代码书写结构决定 - 变量提升(hoisting)也是词法分析阶段完成的:声明被提升至所在函数作用域顶部,赋值留在原位
- 函数内部无论在哪声明
var x,整个函数体都属于它的作用域——这仍是静态、基于位置的规则
对比动态作用域(JavaScript 不采用)
如果 JavaScript 用动态作用域,下面代码会输出 2:
let value = 1;
function foo() { console.log(value); }
function bar() {
let value = 2;
foo(); // 动态作用域下:沿调用栈向上找,找到 bar 内的 value
}
bar();
但实际输出 1,因为 foo 的词法环境在定义时就固定指向全局 value,与谁调用它无关。
ES6 块级作用域也服从词法作用域
let 和 const 引入的块级作用域,同样由代码结构决定:
-
{ }是明确的词法边界,变量只在该块及其内嵌块中有效 - if、for、try 等语句块内的
let不会泄漏到外层函数,因为词法分析时已划清范围 - 块级作用域嵌套在函数作用域内,构成更精细的词法环境层级
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











