作用域和作用域链

Posted 080-hll

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了作用域和作用域链相关的知识,希望对你有一定的参考价值。

  1. 作用域与作用域链

    ①  作用域属于一个函数,一个函数产生了不一样的作用域

    ②  函数名.[[scope]]  函数的隐式属性

    ③  [[scope]] 指的就是作用域,其中存储了运行期的上下文的集合,而这一集合就是作用域链

    ④  查找变量:从作用域链的顶端依次向下查找(在那个函数里面查找变量,就上那个函数的作用域链的顶端依次向下查找变量)

      2. 函数的执行期上下文

    ①  当函数执行的前一刻,会创建一个称为执行期上下文的内部对象AO

    ②  一个执行期上下文定义了一个函数执行时的环境(也就是函数预编译创建AO后下面的步骤操作),函数每次执行时对应的执行上下文都是独一无二的

    ③  多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文会被销毁

   3 . 用代码和图解说明函数执行时的作用域链和执行上下文问题

    ① 代码

 

  function a(){

            function b(){

                var b = 234;

            }

            var a = 123;

            b();

        }

        var glob = 100;

        a();

 

 

    ② 说明

 

        代码执行说明

            1. a被定义时,在其自己所处的环境下(全局环境)创建了一个执行期上下文(GO)将其放在

                其作用域链的顶端,即0位处

            2. a被执行时,会再次创建一个属于自己函数体的执行期上下文(AO)并将这个AO放在其作用域

                链的顶端,即0位处,原先的那个GO会被向下推一位,位于作用域链的1位处

            3. b被定义时,会在其自己所处的环境下创建执行期上下文,此时它处于a的函数体内,因此它会

                继承a原先已经创建好的作用域链,即a的AO和在全局环境下创建的GO

            4. b被执行时,会创建属于自己函数体的执行期上下文(AO)并将其放在其作用域链的顶端,即0

                位处,原先继承的a的AO和GO会以此向下推,位于1位和2位处

            5. b被执行完成后,b自己的执行期上下文会被销毁,从而b函数会回归到b被定义的时刻

            6. a被执行完成后,a自己的执行期上下文会被销毁,从而a函数会回归到a被定义的时刻,因为b函数

                就位于a函数的函数体内,因此当a自己的执行期上下文被销毁的那一刻,b函数也会被永久销毁

            7. 下一次开始,以此循环

 

 

    ③ 图解说明

 

 

 

      a被定义时

                                                     

 

 

技术图片

 

 

 

   

       a被执行时

 

 

 技术图片

 

 

 

      b被定义时

 技术图片

 

 

 

 

      b被执行时

 

 

技术图片

 

 

 

 

      b被执行完成后,会销毁自己的执行上下文,从而剪断作用域链上连接自己的执行上下文的那根线,回归至b被定义时的状态

 

      a被执行完成后,会销毁自己的执行上下文,从而剪断作用域链上连接自己的执行上下文的那根线,回归至a被定义时的状态,但是,因为b函数在a函数的函数体内,所以b会被销毁掉

 

    4.关于作用域与作用域链的其他代码说明

 

代码一

    function a(){

            function b(){

                var b = 234;

                    a = 0;  //这个a是属于a函数自己的,位于a函数的AO上

            }

            var a = 123;

            b();

            console.log(a); //0

        }

        var glob = 100;

        a();

 

代码二

  function a(){

            function b(){

                var b = 234;

                var a = 0;  //这个a是属于b函数自己的,是在他的函数体内定义的,位于b函数的AO上

                console.log(a); //0

            }

            var a = 123;

            b();

            console.log(a); //123

        }

        var glob = 100;

        a();

 

代码三

 function a(){

            function b(){

                function c(){

 

                }

                c();

            }

            b();

        }

        a();

 

代码三代码说明

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

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

                                         1:GO

 

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

                                         1:GO

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

                                         1:aAO

                                         2:GO

 

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

                                         1:aAO

                                         2:GO

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

                                         1:bAO

                                         2:aAO

                                         3:GO

 

以上是关于作用域和作用域链的主要内容,如果未能解决你的问题,请参考以下文章

作用域和作用域链

js 作用域和作用域链

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域和作用域链

理解JavaScript作用域和作用域链(转)

作用域和作用域链