JavaScript作用域详解:全局、函数与块级作用域及作用域链

作者:函数茶馆时间:2026-10-25 05:07:42浏览:368

本文深入解析JavaScript中的三种核心作用域:全局作用域、函数作用域以及ES6引入的块级作用域。详细阐述变量在不同作用域下的可见性与生命周期,解释var、let、const关键字对作用域的影响,并剖析作用域链的查找机制,帮助开发者避免变量污染并优化代码结构。

在深入探讨AO(Activation Object)和BO(Binding Object)之前,有必要先厘清作用域的基本概念。理解这一机制对于后续掌握this指向、变量提升等复杂特性至关重要。

作用域

作用域(Scope)是指变量、函数或对象定义后,其可被访问的有效范围。


console.log(a)
{
    var a=1;
}
function test(){
     var b=2;
}

作用域

从代码执行结果可以看出,外部无法直接访问变量b。这表明作用域具有数据保护机制,防止外部随意访问或修改内部数据。同时,作用域实现了变量隔离,确保不同作用域下的同名变量互不冲突。

在实际开发中,最常用的是全局作用域和函数作用域。随着ES6标准的引入,let和const关键字的出现,又新增了一种块级作用域。

全局作用域

全局作用域指的是所有代码区域均可访问该作用域下的变量、方法及对象。


var a="全局1";
 function test(){
    b="没有带var,隐式转变为全局变量";
    window.c="直接将变量c作为window下也会变全局";
    var d="非全局作用域";
 }
 #第一步 执行test()
test()  #这样才会将方法内的变量进行定义以及赋值
#第二步
console.log(a)
console.log(b)
console.log(c)
console.log(d)

作用域

通常情况下,window对象的属性即为全局变量。例如,window.c 实际上是将变量c作为window对象的一个属性来处理。需要注意的是,在声明变量时务必使用var关键字,否则该变量可能会意外提升为全局变量,导致数据相互污染。

此外,test方法本身也属于全局作用域下的方法。


function test(){
    var a= function(){
        console.log("字面量的方法")
    }
    b=function(){
        console.log("不带var字面量的方法")
    } 
   function test1(){
       console.log("普通声明方法")
   }
     
}
 

作用域

上述代码展示了字面量声明的方法,类似于将函数赋值给一个变量,并将其作为变量对待。这一点在前面的预编译环节中已有演示。

函数作用域

与全局作用域相对,函数作用域并非对所有地方可用,而是限定在特定范围内。通常,在函数内部声明的变量仅在函数内部有效。


function test(){
     var a="非全局作用域";
     console.log(a)
}

这里引出一个问题:全局方法能否访问函数作用域内部的变量?反之,函数内部是否可以包含由子函数生成的函数作用域?这些内部变量之间又能否相互访问?


function test(){
     var a="test方法作用域";
    function test1(){
         var b="test1方法作用域";
        console.log("a的值=",a);
    }
    # 调用函数内部函数
    test1();
     console.log("b的值=",b);
 }

作用域

从代码执行结果可以看出,作用域是分层的。内层作用域可以访问外层作用域的变量,但外部无法访问内部作用域的变量。

if,switch,for ,while

条件语句和逻辑循环(如if、switch、for、while)并非函数,也不会创建新的作用域。在这些代码块中定义的变量将保留在其存在的作用域中。


function test(a){
    if(a>1){
        var b=13;
    }else{
       var b=1;  
    }
    console.log(b);
}

作用域

因此,在使用条件语句和逻辑循环时,应尽量避免在全局作用域下使用。因为代码块中的变量可能会影响其他数据。

块作用域

块作用域的出现通常依赖于let或const关键字之一,否则不会形成块级作用域。

作用域


function test(a){
    const b="23";
    if (a>2){
        const c=3
        console.log("第一个人if---c-----",c)
    }
    if (a>1){
        console.log("第二个人if----b----",b)
        console.log("第二个人if----c----",c)
    }
     
}

作用域

从代码可以看出,如果使用了let和const关键字,变量的作用范围仅限于声明所在的花括号内。因此,第一个if中的c变量在第二个if内部无法获取。当然,这依然遵循内层作用域可以访问外层作用域变量的原则。

如需了解let和const的更多细节,请参考前一篇:地址

作用域链

这一看似神奇的概念,简单来说就是:在作用域内直接查找变量,若未找到则向上一层查找;若仍未找到,则继续向上直到全局作用域,查找结束。


var a=1
var b=3
function test(){
    var a=2
    console.log("a的值",a);
    console.log("b的值",b);
}
 

作用域

补充说明,作用域链的查找逻辑与原型链类似,后续文章将继续探讨。

总结

本文到此结束,希望能对您有所帮助。也欢迎您关注本站以获取更多相关内容!

作者最新文章