首頁  >  文章  >  web前端  >  JS 執行環境、作用域鏈、變數物件和活動物件的關係

JS 執行環境、作用域鏈、變數物件和活動物件的關係

php是最好的语言
php是最好的语言原創
2018-07-27 14:57:172916瀏覽

JS執行環境

執行環境(Execution context,EC)或執行上下文,是JS中一個極為重要的概念

執行環境分為三種(全域執行環境,函數執行環境,evel()執行環境)

js為每一個執行環境關聯了一個變數物件。環境中定義的所有變數和函數都保存在這個物件中

EC的組成

當JavaScript程式碼執行的時候,會進入不同的執行環境(執行上下文),這些執行環境會構成了一個執行環境堆疊(執行上下文堆疊)(Execution context stack,ECS)。請參閱下圖:
JS 執行環境、作用域鏈、變數物件和活動物件的關係

變數物件

變數物件(VO):變數物件即包含變數的對象,除了我們無法存取它外,和普通物件沒什麼差別。變數物件儲存了在上下文中定義的變數和函數宣告

變數物件和活動物件(AO)

  1. 活動物件和變數物件其實是一個東西,只是變數物件是規範上的或是引擎實作上的,不可在JavaScript 環境中訪問,只有到當進入一個執行上下文中,這個執行上下文的變數物件才會被激活,所以才叫activation object

,而只有被啟動的變數對象,也就是在活動對像上的各種屬性才能被存取。

  1. 活動物件是在進入函數執行環境時刻被創建的,它透過函數的 arguments 屬性初始化。 arguments 屬性值是 Arguments 物件。

變數物件和活動物件的關係

未進入執行階段之前,變數物件(VO)中的屬性都不能存取!但是進入執行階段之後,變數物件(VO)轉變為了活動物件(AO),裡面的屬性都能被存取了,然後開始進行執行階段的操作。

它們其實都是同一個對象,只是處於執行環境的不同生命週期。

    AO 实际上是包含了 VO 的。因为除了 VO 之外,AO 还包含函数的 parameters,以及 arguments 这个特殊对象。也就是说 AO 的确是在进入到执行阶段的时候被激活,但是激活的除了 VO 之外,还包括函数执行时传入的参数和 arguments 这个特殊对象。

      AO = VO function parameters arguments

執行環境分析

全域執行環境是最外圍的執行環境,全域執行環境被認為是window對象,因此所有的全域變數和函數都作為window物件的屬性和方法而創建的。
js的執行順序是根據函數的呼叫來決定的,當一個函數被呼叫時,該函數環境的變數物件就被壓入一個環境堆疊中。而在函數執行之後,堆疊將函數的變數物件彈出,把控制權交給先前的執行環境變數物件。

eg:

    var scope = "global"; 
      function fn1(){
         return scope; 
      }
      function fn2(){
         return scope;
      }
      fn1();
      fn2();

示範如下:

JS 執行環境、作用域鏈、變數物件和活動物件的關係

#[[Scope]]  作用域

變數的作用域

變數的作用域就兩種:全域變數和局部變數

    全局作用域:最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的:eg:
          var outerVar = "outer";
          function fn(){
              console.log(outerVar);
      }
          fn();//result:outer
    局部作用域:局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的
     function fn(){
         var innerVar = "inner";
      }
      fn();
      console.log(innerVar);// ReferenceError: innerVar is not defined
    注意:函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
    function fn(){
            age = 18;
        }
        fn();
        console.log(age);// 18

再來看一個有趣的現象:

      var scope = "global";
      function fn(){
         console.log(scope);//result:undefined
         var scope = "local";
         console.log(scope);//result:local;
      }
      fn();

分析:第一個輸出居然是undefined,原本以為它會存取外部的全域變數(scope=”global”),但是並沒有。這可以算是javascript的一個特點,只要函數內定義了一個局部變量,函數在解析的時候都會將這個變數「提前宣告」,他就等價於下面的程式碼:

     var scope = "global";
      function fn(){
         var scope;//提前声明了局部变量
         console.log(scope);//result:undefined
         scope = "local";
         console.log(scope);//result:local;
      }
      fn();

[[Scopr Chain]]  作用域鏈

理解:根據在內部函數可以存取外部函數變數的這種機制,用鍊式查找決定哪些資料能被內部函數訪問,這就是作用域鏈

上面給了環境變數。下面仔細分析下作用域鏈

當某個函數第一次被呼叫時,就會建立一個執行環境(execution context)以及對應的作用域鏈,並將作用域鏈賦值給一個特殊的內部屬性([scope])。然後使用this,arguments(arguments在全域環境中不存在)和其他命名參數的值來初始化函數的活動物件(activation object)。目前執行環境的變數物件始終在作用域鏈的第0位。以上述執行環境分析的小例子為例進行圖解:當第一次呼叫fn1時。

JS 執行環境、作用域鏈、變數物件和活動物件的關係

解析:可以看到fn1活動物件裡並沒有scope變量,於是沿著作用域鏈(scope chain)向後尋找,結果在全域變數物件裡找到了scope,所以就回傳全域變數物件裡的scope值。

再分析下面的程式碼:

    function outer(){
         var scope = "outer";
         function inner(){
            return scope;
         }
         return inner;
      }
      var fn = outer();
      fn();

JS 執行環境、作用域鏈、變數物件和活動物件的關係

總結

說實話,這節真的很難,現在還是似懂非懂,不知道在學前端的朋友你們覺得呢?如果你們覺得這節學會了,可以給我留言,我是真心不懂這節的內容,希望有會的小夥伴可以給我點幫忙!謝謝!

相關文章:

淺談javascript中執行環境(作用域)與作用域鏈

老生常談原生JS執行環境與作用域

相關影片:

js高階物件導向與元件開發影片教學

以上是JS 執行環境、作用域鏈、變數物件和活動物件的關係的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn