JavaScript学习笔记(六):作用域与作用域链

JavaScript的函数是一个特殊的对象,它也有一些属性,如function.name
其中,有一个特殊的属性叫function.[[scope]],它存储着函数的作用域。对于[[scope]]属性的解释如下:

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

那什么是执行期上下文呢?

执行期上下文
当函数执行时,会创建一个称为执行期上下文的内部对象(就是预编译里的AO对象、GO对象)。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毀。

每个函数被创建时都会创建执行期上下文,同时也会产生一个作用域链。什么是作用域链?

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

函数被定义时,将GO放入作用域链的顶端
函数执行时将AO插入到GO的前面,此时AO位于作用域链的顶端

在查找变量时,从作用域链的顶端依次向下查找

举例:

function a(){
    function b(){
        var b = 123;
    }
    
    var a = 456;
    b();
}

var glob = 100;
a();

在上述代码中,
a函数被定义时,作用域链发生如下变化:

a函数执行时,作用域链发生如下变化:

b函数被定义时,作用域链发生如下变化:

b函数执行时,作用域链发生如下变化:

作用域链变化总览:

在作用域链里,只有顶部的执行期上下文对象是函数自身创建的,其余的都是引用的。引用值有数据同步改变的特点。
数据同步改变的举例说明:

fucntion a(){
    function b(){
        var bb = 123;
        aa = 0;
    }
    var aa = 456;
    b();
    console.log(aa);
}
var glob = 100;
a();

console.log(aa);的输出结果为0,因为b函数是引用了a函数的AO对象,而aa是a函数的AO对象的属性,当b函数改变aa的值之后,在a函数访问aa时,显然访问结果是aa的改变后的值。
这说明了b函数里引用的a函数AO对象,和a函数自身创建的AO对象是同一个。

posted @ 2020-05-08 11:59  xiaowus  阅读(132)  评论(0编辑  收藏  举报