本文详细解析JavaScript中的函数作用域特性,指出其与C语言块级作用域的区别。重点阐述变量声明提前(Hoisting)机制,即变量声明会被提升至函数体顶部但赋值保留原位。通过具体代码示例说明局部变量如何遮盖全局变量,以及为何在声明前访问变量会得到undefined而非报错。
JavaScript函数作用域与块级作用域的区别
在C语言等类C编程语言中,花括号内的代码段拥有独立的作用域,变量仅在声明它的代码块内可见,这被称为块级作用域(block scope)。然而,JavaScript并不具备块级作用域的概念,而是采用函数作用域(function scope)。这意味着,变量一旦在函数体内声明,它在整个函数体内部以及该函数嵌套的任何子函数中都是可见的。例如,在以下代码结构中,无论变量i、j和k在函数的哪个位置被定义,它们都在同一个函数作用域内有效。
代码如下:
function text(o)
{
var i=0;
alert(typeof o);
if(typeof o == "string")
{
var j=0;
for(var k=0;k<10;k++)
{
alert(k);//输出0-9
}
alert(k);//输出10
}
alert(j);//输出0
}
变量声明提前(Hoisting)机制解析
JavaScript的函数作用域规定,在函数内部声明的所有变量,在整个函数体内始终可见。一个值得注意的特性是,变量在声明之前即可被访问。JavaScript中这一非正式特性被称为声明提前(hoisting)。也就是说,函数体内所有变量的声明(不包括赋值操作)都会被提升到函数体的最顶端。请参考以下代码示例。
代码如下:
var global="globas";
function globals()
{
alert(global);//undefined
var global="hello QDao";
alert(global);//hello QDao
}
受函数作用域特性影响,局部变量在整个函数生命周期内始终存在。因此,在函数内部,局部变量会遮盖同名的全局变量。然而,实际的赋值操作仅在执行到var语句时才发生。因此,上述代码的执行逻辑等价于:将函数内的变量声明提升至函数体顶部,而将变量初始化保留在原始位置。具体转换如下所示。
代码如下:
var global="globas";
function globals()
{
var global;
alert(global);//undefined
global="hello QDao";
alert(global);//hello QDao
}