相信很多初學者對與JavaScript中的執行環境與作用域鏈不能很好的理解,這裡,我會按照自己的理解同大家一起分享。
一般情況下,我們把執行環境分為全局執行環境和局部執行環境,其中局部執行環境我們又可以稱之為函數執行環境。那麼究竟什麼使執行環境呢?通俗的說,執行環境即為代碼執行時所處的環境。我們下來看一看如下代碼,再進一步分析之。
<script>
var name="zhuzhenwei";
function changeName(){
if (name=="zhuzhenwei"){
name="heting";
}else{
name="zhuzhenwei";
}
}
changeName();
console.log(name); //heting
</script>
如上述代碼,當執行第一個語句時,該語句所在的環境為全局執行環境,應當注意的是:每個執行環境都有一個與之相關聯的變量對象,對於全局執行環境,與它向關聯的對象為window對象。緊接著,下面這條語句聲明了一個函數(注意:這裡僅僅是聲明了函數,沒有被調用之前是不會執行內部代碼的)。 同樣這個函數也是處於全局執行環境的。最後,我們調用了changeName()函數,一旦調用了該函數,那麼立即跳轉到了changeName()函數的執行環境(即函數執行環境),一旦進入執行環境,便開始創建函數內部相應的變量(如函數中假設出現var a=12;這樣的代碼),不調用函數是不會創建的,且與之相關的變量對象我們認為是活動對象(活動對象開始只包含一個變量,即arguments對象),自此開始從上到下執行語句。與此同時,代碼在函數環境中執行時,就會創建變量對象的一個作用域鏈,這個作用域鏈包含changeName()的變量對象和全局變量對象。
作用域鏈實際上就是我們可以通過它從前端到末端可以訪問的范圍,即保證對執行環境有權訪問的所有變量和函數的有序訪問,其中前端是指當前執行代碼所在的變量對象,這裡現在就是changeName()函數的變量對象,末端是全局變量對象,比如說:我們在執行函數時,需要尋找一個標識符,這是就是通過作用域鏈的末端進行尋找,若作用域鏈的末端找不到,就一直向上尋找,直到window對象。雖然在全局環境中我沒有提到作用域鏈,但實際上全局環境中作用域鏈也是存在的,只是只有一個全局變量對象。 很明顯:訪問局部變量比訪問全局變量更快,因為不用向上搜索作用域鏈。顯然,作用域鏈是隨著代碼所處的執行環境的不同而動態變化的。
當執行完changeName()函數之後,即函數執行環境中的代碼執行完成之後,該環境中的局部變量和局部對象會被立即銷毀(如果變量沒有用var聲明,表明是全局變量,不會在局部環境的代碼執行之後銷毀),隨即執行環境由函數執行環境轉向全局執行環境,繼續執行console.log(name);語句。只是,如果我們關閉網頁或浏覽器,全局環境也將被銷毀。
總結如下: