欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

作用域和作用域链

程序员文章站 2022-04-01 10:16:01
...

作用域

作用域就是变量和函数的可访问范围,控制着变量和函数的可见性与生命周期,JavaScript中只有全局作用域与局部作用域

如何判断是全局还是局部作用域?

全局:

  • 最外层函数和在最外层函数外面定义的变量拥有全局作用域
  • 所有末定义直接赋值的变量自动声明为拥有全局作用域
  • 所有window对象的属性拥有全局作用域

局部:

  • 函数内部用var声明的变量
var a=3; //全局变量
            function fn(b){ //局部变量
                c=2; //全局变量
                var d=5; //局部变量
                function subFn(){
                    var e=d; //父函数的局部变量对子函数可见
                    for(var i=0;i<3;i++){
                        console.write(i);
                    }
                    alert(i);//3, 在for循环内声明,循环外function内仍然可见,没有块作用域
                }
            }
            alert(c); //在function内声明但不带var修饰,仍然是全局变量

作用域与执行上下文是完全不同的两个概念。

JavaScript代码的整个执行过程,分为两个阶段,代码编译阶段与代码执行阶段。编译阶段由编译器完成,将代码翻译成可执行代码,这个阶段作用域规则会确定。执行阶段由引擎完成,主要任务是执行可执行代码,执行上下文在这个阶段创建。

作用域和作用域链

作用域链

分析执行上下文的生命周期

作用域和作用域链

我们知道函数在调用**时,会开始创建对应的执行上下文,在执行上下文生成的过程中,变量对象,作用域链,以及this的值会分别被确定。

作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

为了帮助大家理解作用域链,我我们先结合一个例子来说明。

var a = 20;

function test() {
    var b = a + 10;

    function innerTest() {
        var c = 10;
        return b + c;
    }

    return innerTest();
}

test();

在上面的例子中,全局,函数test,函数innerTest的执行上下文先后创建。我们设定他们的变量对象分别为VO(global),VO(test), VO(innerTest)。而innerTest的作用域链,则同时包含了这三个变量对象,所以innerTest的执行上下文可如下表示。

innerTestEC = {
    VO: {...},  // 变量对象
    scopeChain: [VO(innerTest), VO(test), VO(global)], // 作用域链
}

我们可以直接用一个数组来表示作用域链,数组的第一项scopeChain[0]为作用域链的最前端,而数组的最后一项,为作用域链的最末端,所有的最末端都为全局变量对象。