JavaScript作用域分为全局、函数和块级三类:全局变量在脚本最外层声明,全文件可访问;函数作用域中var/function声明的变量仅限该函数内;块级作用域由let/const在{}内声明,仅在对应代码块有效;JS通过静态词法作用域沿作用域链逐层查找变量。

从变量“在哪能用”开始理解,比背定义更直接。作用域不是抽象规则,而是 JS 引擎找变量时实际走的一条路——你写代码的位置,决定了它往哪找。
先记住三类“地盘”:全局、函数、块级
变量的活动范围,就这三种基本划分:
-
全局作用域:脚本最外层声明的变量,比如
var a = 1或let b = 2写在所有函数外面,整个文件都能访问; -
函数作用域:用
var或function在函数里声明的变量,只属于这个函数,连同级的另一个函数都碰不到它; -
块级作用域:用
let或const在{}里声明的变量,比如if、for里面,出了这对大括号就失效。
关键不是“能用”,而是“怎么找”
当你写下 console.log(x),JS 不是猜,而是按固定顺序一层层查:
- 先看当前函数或代码块里有没有
let x或var x; - 没有就往外跳一级,查包裹它的那个函数;
- 再没有,继续往上,直到全局;
- 全程没找到,就报
ReferenceError。
这条查找路径就是“作用域链”,它由代码结构静态决定,跟函数怎么被调用完全无关——这就是“词法作用域”的意思。
立即学习“Java免费学习笔记(深入)”;
动手验证比死记更管用
写几行小代码,马上看清行为差异:
- 把
var x = 10放函数里,再在函数外console.log(x)→ 报错; - 把
let y = 20放if(true) { ... }里,再在if外面console.log(y)→ 报错; - 在函数内调用另一个函数,里面访问外层变量(比如
let z = 30)→ 能读到,因为作用域链连上了。
警惕“声明提升”带来的迷惑
var 声明会“提前登记”,但不提前赋值:
- 写
console.log(a); var a = 5;,输出undefined,不是报错; - 而
console.log(b); let b = 5;直接报错,因为let不提升声明,只存在“暂时性死区”; - 这个细节说明:作用域不只是“能不能用”,还牵扯变量在生命周期不同阶段的状态。


















