JavaScript作用域是引擎查找变量时严格遵循的路径规则,分为全局、函数和块级三种:全局变量挂window(仅var)、函数作用域绑定调用、块级作用域由{}与let/const触发;作用域链决定变量向上逐层查找。

JavaScript 作用域不是“变量在哪能用”的模糊概念,而是**引擎查找变量时严格遵循的一套路径规则**。全局作用域和函数作用域的区别,不在于“写在哪”,而在于**变量绑定的位置、可访问的边界,以及生命周期是否受函数调用控制**。
全局作用域:所有代码都能看到的“公共广场”,但别乱扔东西
在 标签最外层或独立 JS 文件顶层声明的变量(var、let、const),就进了全局作用域。浏览器中它会自动挂到 window 上(仅 var 声明的会)。
-
var globalA = 1→window.globalA存在,可跨 script 访问 -
let globalB = 2→window.globalB是undefined,但它仍是全局变量,任何地方都能读写 - 直接写
noVar = 3→ 隐式挂到window.noVar,污染严重,禁止使用 - 全局变量不会被 GC 回收,直到页面关闭;命名冲突风险高(比如两个库都定义了
data)
函数作用域:每次调用都新建一个“隔离房间”,关上门变量就失效
函数内部用 var 声明的变量,只属于这个函数——注意,是“函数作用域”,不是“块作用域”。哪怕它写在 if 或 for 里,只要没用 let/const,它就逃不出这个函数。
-
function fn() { var x = 10; if (true) { var y = 20; } console.log(y); // ✅ 输出 20 }——y不是if的,是fn的 -
console.log(x); // ❌ ReferenceError—— 函数外完全不可见 - 每次调用
fn()都创建全新作用域,互不影响(形参也是局部变量) - 函数执行完,若无闭包引用,整个作用域连带变量通常被销毁
块级作用域(ES6):不是函数作用域的子集,而是并列的新玩家
很多人误以为 if{} 或 for{} 里的 let 变量属于“函数作用域的一部分”——错。它是独立的块级作用域,和函数作用域平级,由 {} 和 let/const 共同触发。
-
function test() { if (true) { let z = 30; } console.log(z); // ❌ ReferenceError }——z只活在那个{}里 -
var在块内声明 ≠ 块级作用域:if(true) { var w = 40; } console.log(w); // ✅ 40 -
catch块也有自己的作用域:try { throw 1; } catch(e) { console.log(e); } console.log(e); // ❌ e is not defined
作用域链:变量不是“就近找”,而是“向上逐层查”
函数执行时,JS 引擎按“当前作用域 → 外层函数作用域 → … → 全局作用域”顺序查找变量。找不到就报 ReferenceError。这不是语法糖,是运行时真实发生的链式查找。
立即学习“Java免费学习笔记(深入)”;
function outer() { const a = 'outer'; function inner() { console.log(a); // ✅ 找到 outer 里的 a } inner(); }- 嵌套越深,链越长,性能影响微乎其微,但理解它才能避开“为什么这里能访问到那个变量”的困惑
- 闭包的本质就是:内层函数记住了它创建时所处的作用域链,即使外层函数已执行完毕
var 当成块级作用域用,或者在函数里漏写 var/let/const 导致意外挂全局。这些错误不会立刻报错,却会在后期引发难以追踪的覆盖和内存泄漏。











