JavaScript全局变量与局部变量
谈 JavaScript 全局变量和局部变量之前,先记住三件事:查找变量走的是作用域链;用 var 时没有块级作用域;函数里声明的变量在整个函数体都有效。
ES6 的 let / const 才真正有块级作用域。 下文例子全部沿用原文的 var,这是面试里仍经常被追问的经典行为。
一、作用域链
inner 里的 alert(rain) 会一层层往外找:inner → rainman → 全局。 内层没定义就继续向外,直到全局对象上的 rain = 1,最终弹出 1。
这条链上有三个对象,顺序是 inner、rainman、window。引擎要的是变量 x 时,从链头第一个对象找起,没有再找下一个。
二、局部变量盖住同名全局变量
函数体内同名局部变量优先级更高。下面 check 里弹出 100,外面仍是 1:
三、var 没有块级作用域
这是相对 C 系语言更「松」的地方。if / for 里用 var 声明的 i、j、k,作用域仍是整个 rainman 函数:
循环结束后 k 是 3,if 外面也能读到 j。若改成 let k,循环外再读 k 会 ReferenceError。
四、函数内声明的变量整函数可见
内层 man 改的是外层 rain 里的 x,所以弹出 100:
同一规则会造成「先读后声明」的错觉:
因为 var x 在整个 rain 里都有效,同名全局 x 被挡住。 第一次 alert(x) 时局部 x 只完成了声明、尚未赋值,所以是 undefined。等价于:
五、不用 var 就是全局变量
赋值给一个从未声明的标识符,会在全局对象上创建属性。新手常这样留下一堆全局变量:
严格模式('use strict')下这行会报 ReferenceError,建议养成始终声明的习惯。
六、全局变量是 window 的属性
浏览器里用 var 声明的全局,等价于给 window 添属性:
等同于:
| 规则 | 含义 | 例子里的结果 |
|---|---|---|
| 作用域链 | 由内向外找标识符 | inner 能读到全局 rain=1 |
| 同名遮蔽 | 局部优先于全局 | 函数内 100,函数外 1 |
| 无块级(var) | if/for 里的 var 仍属整个函数 | 循环外仍能读到 k、j |
| 声明提升 | 整个函数都能看到该绑定 | 赋值前读取得到 undefined |
| 漏写 var | 隐式全局 | 函数外也能 alert(x) |
一句话总结:用 var 时变量只认函数作用域:沿作用域链查找,局部盖全局,块挡不住,漏写 var 就会漏到 window 上。
转载请注明来源:JavaScript全局变量与局部变量







