標籤:全域 作用 不用 語言 order 表達 編譯 ima div
執行環境定義了變數或函數有權訪問的其他資料,決定了它們各自的行為。每個執行環境都有一個與之關聯的
變數對象,環境中定義的所有變數和函數都儲存在這個對象中。我們編寫的代碼是無法訪問這個對象的,但解析器在處理資料時會在後台使用它。 全域執行環境是最外圍的一個執行環境,在Web瀏覽器中,全域執行環境被認為是window對象,因此所有全域變數和函數都是作為window對象的屬性和方法來建立的。某個執行環境中的所有代碼執行完畢後,該環境就會被銷毀,儲存在其中的所有變數和函數定義也隨之銷毀。 每個函數都有自己的執行環境,當執行流進入一個函數時,函數的環境就會被推入一個環境棧中,在函數執行後,棧將其環境彈出,將控制權返回給之前的執行環境。ECMAScript程式中的執行流正是由這個方便的機制控制著。 當代碼在一個環境中執行時,會建立變數對象的一個
範圍鏈。範圍鏈的用途,是保證對執行環境有權訪問的所有變數和函數進行的有序訪問。範圍鏈的前端,始終都是當前執行的代碼所在環境的變數對象,如果這個環境是函數,則將其
使用中的物件作為變數對象。活動變數最開始時只包含一個變數,即
arguments對象(這個對象在全域環境中是不存在的)。範圍鏈中的下一個變數對象來自包含(外部)環境,再下一個變數對象則來自於再下下個包含(外部)環境,這樣一直延續到全域執行環境,全域執行環境的變數對象始終都是範圍鏈中的最後一個對象。
標識符解析是沿著範圍鏈一級一級向上(外)搜尋
標識符的過程。搜尋過程始終從範圍鏈的前端開始,然後逐級向後回溯,直至找到標識符為止。(比如:在全域執行環境中定義了一個name屬性,當在一個函數中使用了未聲明的變數name,這時,js在先行編譯時,會向上回溯直到找到name屬性位置。) 中矩形表示特定的環境。其中
內部環境可以通過範圍鏈訪問所有的外部環境,但外部環境不能訪問內部變數環境中的任何變數和函數。這些環境之間的練習是線性,有次序的。每個環境變數都可以向上搜尋範圍鏈,以查詢變數和函數名;反之則是不行。 注意,
函數參數也被當作變數來對待,因此其訪問規則與執行環境中的其他變數相同。1、延長範圍鏈 雖然執行環境的類型總共只有兩種——全域和局部(函數)。但還是可以通過其他方法來
延長範圍鏈。因為有些語句在範圍鏈的前端臨時增加了一個變數對象,該變數對象會在代碼執行後被移除。當執行流進入下列任一語句時,範圍鏈就會得到加長:
- try-catch語句的catch塊
- with語句
這兩個語句都會在範圍鏈前端增加一個變數對象。對於with語句來說,會將指定的對象添加到範圍鏈中。對於catch語句來說,會建立一個新的變數對象,其中包含的是被拋出的錯誤對象的聲明。 2、沒有塊級範圍
if(true){ var color = "blue";}alert(color);
注意:如果是在C#、java中,color會在if語句執行完畢後被銷毀,但在JavaScript中,if語句中的變數聲明會將變數添加到當前的執行環境中(在這裡是全域執行環境)。在使用for語句時尤其要牢記這一差異,例如
for (var i=0;i<10;i++){ doSonmething(i);}alert(i); //10
對於C#,java語言來說,for語句初始設定變數的運算式所定義的變數,最會存在於迴圈的環境中。而對JavaScript來說,for語句建立的變數i即使for迴圈結束後,也依舊會存在與迴圈外部的執行環境中。
在使用var關鍵字聲明變數時,這個變數將被自動添加到最接近的環境中。在函數內部,最接近的環境就是函數的局部環境。在with語句中,最接近的環境是函數環境。所入初始設定變數時沒用用var聲明,該變數會被自動添加到全域環境。
查詢標識符(變數等),當在某個環境中為了讀取或寫入為引入一個標識符時,就必須通過搜尋來確定該標誌符實際代表什麼。搜尋過程從範圍鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。如果局部變數中有,搜尋停止,如果沒有在逐級向上搜,直到全域環境。如果全域環境中也沒有找到這個標識符,則意味著該變數沒有聲明過。
通過下面這個執行個體,可以理解查詢標識符的過程:
var color="blue";function getColor(){ return color;}alert(getColor()); //blue
調用本例中的函數getColor()時會引用變數color。為了確保變數color的值,將開始一個兩步走的搜尋過程。首先,搜尋getColor()的變數對象,尋找其中是否包含一個名為color的標識符。在沒有找到的情況下,搜尋到下一個變數對象(全域環境的變數對象),然後在那裡找到了名為color的標識符。因為搜尋到了定義這個變數對象,搜尋過程也宣告結束。
在這個搜尋過程中,如果存在一個局部的變數的定義,則搜尋會自動停止,不會再進入外部環境進行搜尋。
變數查詢也不是沒有代價。很明顯,訪問局部變數要比訪問全域變數快的多,因為不用向上搜尋範圍鏈,但這個差別在將來的最佳化下會變得可以忽略不計。
原文:https://www.cnblogs.com/zxj159/archive/2013/05/17/3084598.html
JavaScript之執行環境及範圍