JS变量作用域取决于访问范围而非代码行数:全局变量在脚本全程可访问,挂载于全局对象;局部变量分函数作用域(var)和块级作用域(let/const),均在对应范围内有效且执行结束即销毁;同名时近者优先,通过静态作用域链查找。

JS 中全局变量和局部变量的作用域,核心在于“变量在哪能被访问到”,而不是简单看它写在第几行。作用域本质是一套查找规则:当代码里用到一个变量名,JS 引擎会按固定路径一层层向上找,找到就用,找不到就报错。
全局变量的作用域:从脚本开始就存在,处处可查
全局变量在最外层(函数之外)声明,或者没用 var/let/const 直接赋值(如 s = 10),它就自动挂到全局对象上(浏览器是 window,Node 是 global)。这意味着:
- 任何地方——函数内、if 块里、for 循环中——都能读取或修改它
- 它的生命周期贯穿整个程序运行期,直到页面关闭或进程退出
- 它会成为全局对象的一个属性,比如 window.s 可以访问到 s = 10
局部变量的作用域:只在“自己家”有效,出了门就失效
局部变量分两类,作用域边界不同:
- 函数作用域:用 var 或函数声明定义在函数内部的变量,整个函数体(包括嵌套函数)都能访问,但函数外完全不可见
- 块级作用域:用 let 或 const 在 {} 内声明的变量(比如 if、for、while 里面),只在这一对花括号范围内有效,连同级的其他语句都访问不到
它们的共同点是:每次函数调用或进入块时才创建,执行结束就销毁,不占用长期内存。
优先级和遮蔽:同名时,近的说了算
如果函数内声明了一个和全局变量同名的局部变量,那么在这个函数里,所有对该变量的读写操作都只影响局部变量,全局的那个被“遮蔽”了。这不是覆盖,而是查找时先找到最近的作用域,就不会再往上找了。
例如:var a = 1; function f() { console.log(a); var a = 2; } 执行时输出 undefined,因为 var a 被提升到函数顶部,但赋值还没发生,此时函数作用域里的 a 已存在且未初始化。
作用域链:查找变量的真实路径
每个函数在定义时,就记住了它“出生地”的词法环境。执行时,JS 引擎会沿着这条静态确定的链向上查找变量:当前作用域 → 外层函数作用域 → … → 全局作用域。这个链就是作用域链,它不受调用位置影响,只取决于函数怎么写的。


















