day 20 作用域

一、全局变量 局部变量

 function test ( ){
      	var a = 123;
        function demo(){
      		var b = 234;
      		console.log(a);
      	}
        demo();
        console.log(b);
 }
 test();

局部变量可以访问全局变量
全局变量不能访问局部变量

二、作用域精解

运行期上下文
      当函数执行前一刻 会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁

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

[[scope]]作用域链:
      [[scope]]中储存的执行期上下文对象的集合,成链式连接。每次执行一个函数前都会创建一个执行期上下文,放在作用域顶端。查找变量就是从顶端往下扫描。

1、构建作用域过程:

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

a defined --> a.[[scope]] --> 0 :GO
在这里插入图片描述
a doing ( b defined )–> a.[[scope]]/ b.[[scope]] --> 0 : AO , 1 : GO

在这里插入图片描述
a doing ( b defined )–> a.[[scope]]/ b.[[scope]] --> 0 : AO , 1 : GO

在这里插入图片描述
b doing --> b.[[scope]] --> 0 : AO , 1 : AO , 2 : GO

在这里插入图片描述
       当b执行完后销毁自己的执行期上下文,b执行完意味着a也执行完毕,a销毁自己的执行期上下文,同时删除b函数。等待下一次执行a函数时创建全新的执行期上下文,构建新的作用域链。

2、作用域链下A0对象和外面的包含函数产生的AO为同一个

function a(){ 
    function b(){
        var b = 234;
        a =  0;
    }
    var a = 123;
    console.log(a); // 123
    b();
    console.log(a); // 0
}
var Global = 100;
a();
console.log(a); // function a(){ ...}

3、构建作用域链精解

function a(){
     function b(){
        function(){ 
        }
        c();
     }
     b();
}
a();       
  • ps: ( a )( b )( c )是下标便于区分。
    1、首先a被定义,生成a.[[scope]], 创建GO放在作用域里。
    2、然后a执行,创建(a)AO,放在作用域顶端。与此同时b被定义,作用域里放着此时a.[[scope]]里的(a)AO、GO。
    3、然后b执行,生成b.[[scope]], 创建(b)AO,放在作用域顶端。与此同时c被定义,作用域里放着此时b.[[scope]]里的(b)AO、(a)AO、GO。
    4、最后c执行,生成c.[[scope]], 创建©AO,放在作用域顶端。

  • 所有的(a)AO、(b)AO、 ©AO都是同一个执行期上下文
    每次执行完都销毁自己的执行期上下文,然后等待再次被定义与执行。

  • 从上面的过程看,最底层的函数,包含的执行期上下文越多,所以才有那两句话:
    局部变量可以访问全局变量
    全局变量不能访问局部变量

猜你喜欢

转载自blog.csdn.net/LGT970116/article/details/82975523