JavaScript 变量作用域机制:预编译、函数块与全局访问
本文解析 JavaScript 变量作用域的核心机制,指出其基于函数块而非语句块划分。通过预编译阶段确定变量声明位置,解释了局部变量如何覆盖全局变量及 undefined 现象。文章结合代码示例,详细演示了 var 声明的变量提升、函数内外变量访问规则,以及通过 window 对象访问全局变量的具体方法,帮助开发者避免常见的变量污染与引用错误。
JavaScript 作用域的划分标准
JavaScript 中作用域(scope)的划分依据是函数(function)代码块,而非 if、while 或 for 等语句块。这意味着在语句块内声明的变量,其作用域并不局限于该语句块内部。
语句块与函数块的作用域差异
<script>
function f1(){
alert("before for scope:"+i);
//i未赋值(并不是没有声明!使用未声明变量或函数会导致致命错误从而中断脚本执行)
//此时i值为undefined
for(var i=0; i<3;i++){
alert("in for scope:"+i);}
//i的值是0,1,2
alert(“after for scope:”+1);
//i的值是3,此时已经在for scope之外,但i的值仍然保留为3
while(true){
var j=1;
break;}
alert(j);
//j的值是1,此时已经在while scope之外,但j的值仍然保留为1
if(true){
var k=1;
}
alert(k);
//k的值为1,此时已经在if scope之外,但k的值仍保留为1
}
f1();
//此时在函数块外调用函数,再次输出存在于f1这个function scope里的i j k变量
alert(i);
//error!!!原因是这里的i未声明(不是未赋值,区别f1的第一行输出),脚本错误,程序结束!
alert(j);
//未执行
alert(k);
//未执行
</script>
变量预编译与作用域确定
JavaScript 引擎在执行代码前,会先对整个脚本文件进行预编译处理,分析其中的声明部分(包括局部变量声明),从而确定每个变量的实际作用域。以下代码示例展示了这一机制的具体表现:
预编译导致的变量覆盖与 undefined
<script>
var x=1;
function f2(){
alert(x);
//x的值为undefined!这个x并不是全局变量,因为在function scope已经又声明了一个重名的局部变量,所以全局变量的参数a被覆盖了。
说明了JavaScript在执行前会进行预编译,函数体内的x就被指向局部变量,而不是全局变量。此时x只有声明,没有赋值,所以为undefined
x=3;
alert(x);
//x值为3.但还是局部变量
var x;
//局部变量x在这里声明
alert(x);
//值为3
}
f2();
alert(x);
//x值为1,并不是在function scope内,x的值为全局变量的值。
</script>
局部变量对全局变量的覆盖与恢复
当局部变量与全局变量同名时,局部变量的作用域会覆盖全局变量。一旦退出局部变量的作用域,程序将重新访问全局变量。在局部变量与全局变量交互的场景中,需注意变量声明与赋值的顺序差异。
全局变量的显式访问方法
若要显式访问全局变量,可通过 window 对象的属性进行调用,语法为 window.globalVariableName。
通过 window 对象访问全局变量示例
<script>
var a=1;
function f3(){
alert(window.a);
//a位1,这里的a是全局变量
var a=2;
alert(a);
}
f3();
alert(a);
</script>
以上内容涵盖了 JavaScript 全局变量与局部变量的核心概念及访问方式,供读者参考与实践。
JS创建数组的两种方式:字面量[]与new Array()的区别
2026-11-05 18:02:28
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
