zoukankan      html  css  js  c++  java
  • 理解作用域链

    先来看两个例子

    var x = 10;
    
    bar();   //10
    function foo(){
      console.log(x);
    }
    
    function bar(){
      var x = 30;
      foo();
    }
    

    解析

        执行bar,相当于执行foo(),foo里面要输出x,我们首先要从foo自己的作用域下面去找
        foo里边是没有声明x的,然后我们会到foo的词法作用域去找,也就是声明foo的作用域去找。
        在这里foo的词法作用域就是全局作用域,全局作用域里声明的x=10,所以输出10
    
     var x = 10;
        bar();  //30
    
        function bar(){
           var x = 30;
           function foo(){
               console.log(x); 
          }
           foo();
       }
    

    解析

        执行bar(),就会执行foo().foo里输出x,我们首先找foo的作用域里,发现没有声明x
        那就接着找foo的词法作用域。也就是声明foo的作用域,发现有x=30,于是输出了30
    

    几个相关的概念

    一 、execution context (执行上下文,也叫执行环境):

    • 执行上下文定义了变量和函数有权访问的其他数据。

    • 每个执行环境,都有一个与之关联的变量对象(variable object).环境中定义的所有变量和函数都保存在这个对象中。(我们编写的代码无法访问这个对象,但是解析器可以)

    • 全局执行环境,是最外围的一个执行环境,在WEB浏览器中,全局执行环境被认为是 window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。

    • 某个执行环境中的所有代码都执行完毕之后,该环境被销毁,保存在其中的所有变量和函数定义,也随之销毁。(全局执行环境,直到应用程序退出——例如关闭管业或浏览器时才会被销毁)

    • 每个函数都有自己的执行环境

    二 、scope chain(作用域链),activation object(活动对象)

    • 当代码在一个环境中执行时,会创建变量对象的一个作用域链。

    • 作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始只包含一个arguments对象(这个对象在全局执行环境中是不存在的)

    • 作用域链中的下一个变量对象来自包含(外部)环境,以此类推,一致延续到全局执行环境。

    • 全局执行环境的变量对象,始终都是作用域链中的最后一个对象。

    三 、[[Scope]]属性

    • 函数是特殊的可执行对象。
    • 既然是对象,就可以拥有属性。
    • 函数中存在着一个内部属性[[Scope]](我们不能使用,供JS引擎使用)
    • 函数被创建时,这个内部属性就会包含函数被创建的作用域中对象的集合。
    • 这个集合呈链式连接,被称为函数的作用域链
    • 作用域链上的每一个对象被称为变量对象(variable object)
    • 每一个变量对象都以键值对形式存在

    执行顺序

            //范例1
            var x = 10;
    
            bar();  //10
            function foo() {
                console.log(x);
            }
    
            function bar() {
                var x = 30;
                foo();
    

    首先

          1.代码在一开始会有声明前置,
          var x ;
          funciton bar();
          funciton foo();
          之后再去执行 x=10;
    
          在一开始的时候,这个执行环境叫全局执行环境(global Context),也就是全局作用域。
    
          全局执行环境里包含了两个对象,一个是活动对象(AO),一个是Scope属性
          global Context = {
              AO : {
                  x : 10;
                  bar : function;
                  foo : function;
               },
              Scope:null
           }
    
        声明bar时  得到下面:
        bar().[[Scope]]  = global Context.AO
        声明foo时  得到下面:
        foo().[[Scope]]  = global Context.AO
        
        执行代码的时候,当我们需要一个值,会首先从它的活动对象里去找,如果找不到就要到它的[[Scope]] 里去找。
    
       2.当调用bar()时,进入bar的执行上下文
        因为bar里值声明了一个x,所以bar的活动对象里只有一个x
        barContext = {
          AO : {
              X : 30
          },
          Scope :bar.[[Scope]]   //global Context.AO
        }
        
       3. 当调用foo()的时候,进入foo的执行上下文
        fooContext = {
        //foo里没有声明变量,foo也没有参数,所以foo的活动对象是空的
        AO:{}
        Scope:foo.[[Scope]]    //global Context.AO
      }
  • 相关阅读:
    hdu 3032 Nim or not Nim? (SG函数博弈+打表找规律)
    HDU 2147 kiki's game(博弈)
    C++学习47 文件的概念 文件流类与文件流对象 文件的打开与关闭
    C++学习46 getline()函数读入一行字符 一些与输入有关的istream类成员函数
    C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符
    C++学习44 格式化输出,C++输出格式控制
    C++学习43 输入输出有关的类和对象
    C++学习42 输入和输出的概念
    C++学习41 exception类
    C++学习40 抛出自己的异常
  • 原文地址:https://www.cnblogs.com/wjlbk/p/12633282.html
Copyright © 2011-2022 走看看