執行環境其實就是一個變量或者一個函數有權通路的所有其他資料集合。在每個執行環境中都有一個與之相關聯的變量對象(VO),在目前環境中定義的所有變量和函數都會儲存在這個變量對象中。VO我們是無法通路的,隻有解析器處理資料的時候才有權在背景使用它。
全局執行環境是最外圍的環境,一般是window對象,是以我們定義的所有全局變量、函數都被建立為window對象的屬性和方法。當某個執行環境中的代碼執行完畢,該環境将被銷毀,其中的所有變量、函數也同樣。
函數在被調用時會建立自己的執行環境,并推入一個棧中。當執行完畢,再彈出以傳回到原來的執行環境中去。這個類似于C語言中的函數調用。
代碼在執行到一個環境中時,會建立由VO構成的作用域鍊。假如A的執行環境a中調用了函數B産生新的執行環境b,那麼b的作用域鍊最前端将會儲存b的VO,鍊的下面緊接着是它的包含作用域a的VO,如此一直到鍊的最後是全局執行環境的VO。
辨別符的解析器是就是沿着目前環境的作用域鍊來搜尋的。如:
1
2
3
4
5
6
7
var hello = “coomy”;
function say(){
var hello2 = “ming”;
alert(hello);
}
say(); //coomy
alert(hello2); //error 404
當say函數被調用時,對hello進行解析時,會掃描作用域鍊。首先是自己的VO,發現并沒有這個變量,然後開始搜尋其上層包含環境的VO,發現了hello。但是外層的作用域中是無法通路其所包含的作用域中的變量的,這些文法都是類似于C語言中的作用域概念。當然,作用域鍊可以以此類推到多層的嵌套中去。
注意,函數的參數也是被當作變量來對待的,通路規則與執行環境中的其他變量相同。
定義補充一下作用域鍊
當代碼在一個執行環境中執行時(例如一個函數内),會建立由變量對象構成的一個作用域鍊(scope chain),它是保證對執行環境有權通路的所有變量和函數的有序通路。作用域鍊的前端,始終都是目前執行代碼所在環境的變量對象。如果這個環境是一個函數,則将其活動對象(activation object)作為變量對象。活動對象在最開始隻包含一個變量,即arguments對象(這個對象在全局環境中是不存在的,但在一個函數中呢它是這個函數目前活動對象中的第一個屬性-activation object.arguments)。作用域鍊中的下一個對象來自包含(外部)環境,而再下一個變量對象則來自下一個包含環境。這樣,一直延續到全局執行環境,全局執行環境的變量對象始終都是作用域鍊中的最後一個對象。辨別符解析是沿着作用域鍊一級一級地搜尋辨別符的過程。搜尋過程始終從作用域鍊的最前端開始,然後逐漸地向後回溯,直到找到辨別符為止(如果找不到辨別符,通常會導緻錯誤發生)。
請看以下代碼:
8
9
10
11
var color = "blue";
function changeColor(){
var a="3";
if(color=="blue" ){
color="red";
}else{
color="blue";
changeColor();
alert("Color is now "+color);
在上面這函數中,函數changeColor()的作用域鍊包含兩個對象:它自己的變量對象(也就是changeColor這個函數的活動對象,對開發人員來說是不可見的隻要js解析器短簡,目前這函數的活動對象目前有兩個屬性:arguments和a兩個)和全局的變量對象(全局對象中有屬性color)。可以在函數内部通路變量color,就是因為可以在這個作用域鍊中找到它咱們畫個簡單的圖:

内容來自:http://www.dev26.com/blog/article/208/1