javascript之作用域及作用域链

在看js权威指南时,感觉上面讲的不太详细,没看懂什么意思,就找了有关的视频,将视频讲解记录下来并加以整理,防止自己遗忘,以下是正文。

在介绍作用域与作用域链之前,先要了解运行(执行)上下文的概念,运行期上下文的定义为:当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被撤销。

[[scope]]:每个javascript函数都是一个对象,对象中有些属性我们可以访问,有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个,[[scope]]就是我们所说的作用域,其中存储了运行期上下文的集合,是对象的一个隐式属性,不能使用。

作用域链:[[scope]]中所存储新的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

查找变量:在哪个函数中查找变量,就在哪个函数生成的作用域链的顶端(第零位)依次向下查找。

举个例子:

function a() {
    function b() {
        var b = 234;
    }
    var a = 123;
    b();
}
var glob = 100;
a();

// 函数被定义时,其scope中就存了东西,存的Global Object

a定义 a[[scope]]中存0:GO{}(全局对象)

a执行 a[[scope]]中存0:AO{}(活动对象),

                                      1:GO{}

b被创建时,保存了a的劳动成果(换句话说,b是站在a的肩膀上看世界),与a的作用域链完全一样

b在执行时,也要生成自己的执行上下文(AO),置于作用域链顶端

b执行完之后,销毁自己的执行上下文,(与自己的AO断开联系,对比上图红线部分表示已断开)

b执行完后,因为b()是a()的最后一条语句,因此a要销毁自己的执行上下文,b函数也因此被销毁,b函数(已被销毁)与自己的作用域链断开链接(从图中可以看出b函数已经不存在)

当a()被再次执行时,就会生成全新的执行上下文,又产生一次b()的定义,又一个全新的b函数保存了a的劳动成果 ,再次等待执行,执行时又生成一个全新的执行上下文的作用域链。

又一个栗子:

function a() {
    function b() {
        function c() {
        }
        c();
    }
    b();
}
a();

a defined a.[[scope]]-->0:GO;

a doing    a.[[scope]]-->0:aAO

                                     1:GO;

a的执行产生b的定义

b defined b.[[scope]]-->0:aAO

                                     1:GO;

b doing    b.[[scope]]-->0:bAO

                                     1:aAO

                                     2:GO;

b的执行产生c的定义

c defined c.[[scope]]-->0:bAO

                                    1:aAO

                                    2:GO;

c doing   c.[[scope]]-->0:cAO

                                   1:bAO

                                   2:aAO

                                   3:GO;

当c被执行完,就返回到c被定义的状态,如果c在此状态又执行一次,则生成一个新的cAO,与之前的cAO是不同的,但bAO,aAO,GO都是相同的,因为都是基于c的定义。

得出结论:访问函数时,只要访问其作用域链就可以,(只能从里往外看,不能从外往里看),所有的AO和BO都是一样的

注:只有a执行才会导致b被定义

猜你喜欢

转载自blog.csdn.net/line233/article/details/83148321