執行環境及做用域鏈

  執行環境(execution context,爲簡單起見,有時也被稱爲「環境」)是JavaScript 中最爲重用的一個概念。執行環境定義了變量或函數有權訪問的其餘數據,決定了它們各自的行爲。每一個執行環境都有一個與之關聯的變量對象(variable object),環境中定義的全部變量和函數都保存在這個對象中。雖然咱們編寫的代碼沒法訪問這個變量,但解析器在處理數據時會在後臺使用它。前端

  全局執行環境是最外圍的一個執行環境。根據 ECMAScript 實現所在的宿主環境不一樣,表示執行環境的對象也不同。外 Web瀏覽器中,全局執行環境被認爲是 window 對象,所以全部全局變量和函數都是做爲window 對象的屬性和方法建立的。某個執行環境中的全部代碼執行完畢後,該環境被銷燬,保存在其中的全部變量和函數定義也隨之銷燬(全局執行環境直到應用程序退出——例如關閉網頁或瀏覽器——時纔會被銷燬)。瀏覽器

  每一個函數都有本身的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行以後,棧將其環境彈出,把控制權返回給以前的執行環境。ECMAScript 程序中的執行流正是由這個方便的機制控制着。函數

  當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈(scope chain)。做用域鏈的用途,是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域鏈的前端,始終都是在當前執行的代碼所在環境的變量對象。若是這個環境是函數,則將其活動對象(activation object)做爲變量對象。活動對象在最開始時只包含一個變量,即arguments 對象(這個對象在全局環境中是不存在的)。做用域鏈中的下一個變量對象來自包含(外部)環境,而再下一個變量對象則來自下一個包含環境。這樣,一直延續到全局執行環境;全局執行環境的變量對象始終都是做用域鏈中的最後一個對象。spa

  標識符解析是沿着做用域鏈一級一級地搜索標識符的過程。搜索過程始終從做用域及的前端開始,而後逐級地向後回溯,直到找到標識符爲止(若是找不到標識符,一般會致使錯誤發生)。code

  請看下面的實例代碼:對象

var color = "blue";
   
   function changeColor() {
       if(color === "blue"){
           color = "red";
       } else {
           color = "blue";
       }
   }
   
   changeColor();
   alert("color is now " + color);

  在這個簡單的例子中,函數changeColor() 的做用域鏈包含兩個對象:它本身的變量對象(其中定義着 arguments 對象)和全局環境的變量對象。能夠在函數內部訪問變量 color ,就是由於能夠在這個做用域鏈中找到它。blog

  此外,在局部做用域中定義的變量能夠在局部環境中與全局變量互換使用,以下面這個例子所示:ip

var color = "blue";
   
   function changeColor() {
       var anotherColor = "red";
       
       function swapColors() {
           var temColor = anotherColor;
           anotherColor = color;
           color = temColor;
           
           //這裏能夠訪問 color, anotherColor, temColor
       }
       //這裏能夠訪問 color, anotherColor, 可是不能訪問temColor
       
       swapColors();
   }
   
   changeColor();

  以上代碼共涉及3個執行環境:全局環境、changeColor() 的局部環境和 swapColors() 的局部環境。全局環境中有一個變量 color 和 一個函數 changeColor()。changeColor() 的局部環境中有一個名爲 anotherColor 的變量和一個名爲 swapColors() 的函數,但它也能夠訪問全局環境中變量 color。 swapColor() 的局部環境中有一個變量 temColor,該變量只能在這個環境中訪問到。不管全局環境仍是 changeColor() 的局部環境都無權訪問 temColor。然而,在 swapColors() 內部則能夠訪問其餘兩個環境中的全部變量,由於那兩個環境是它的父執行環境。下圖形象的展現了前面這個例子的做用域鏈。作用域

 

  圖中矩形表示特定的執行環境。其中,內部環境能夠經過做用域鏈訪問到全部的外部環境,可是外部環境不能訪問內部環境中的任何變量和函數。這些環境之間的聯繫是線性、有次序的。每一個環境均可以向上搜索做用域鏈,以查詢變量和函數名;但任何環境都不能經過向下搜索做用域鏈而進入另外一個執行環境。對於這個例子中的swapColor() 而言,其做用域鏈中包含3個對象:swapColor()的變量對象、changeColor() 的便利對象和全局變量對象。swapColors() 的局部環境開始時會先在本身的變量對象中搜索變量和函數名,若是搜索不到再搜索上一級做用域鏈。changeColor() 的做用域鏈中包含兩個對象:它本身的變量對象和全局變量對象。這就是說,它不能訪問 swapColor()的環境。io

相關文章
相關標籤/搜索