天天看點

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

   作用域就是變量和函數的可通路範圍,控制着變量和函數的可見性與生命周期,在javascript中變量的作用域有全局作用域和局部作用域。

    全局和局部作用域下面用一張圖來解釋:

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

   單純的javascript作用域還是很好了解的。

  全局執行環境是最外層的一個執行環境,在web浏覽器中全局執行環境是window對象,是以所有全局變量和函數都是作為window對象的屬性和放大建立的。每個函數都有自己的執行環境,當執行流進入一個函數的時候,函數的環境會被推入一個函數棧中,而在函數執行完畢後執行環境出棧并被銷毀,儲存在其中的所有變量和函數定義随之銷毀,控制權傳回到之前的執行環境中,全局的執行環境在應用程式退出(浏覽器關閉)才會被銷毀。

  當代碼在一個環境中執行時,會建立變量對象的一個作用域鍊(scope chain)來保證對執行環境有權通路的變量和函數的有序通路。

    用一張圖來解釋作用域鍊的運作:由裡向外執行。

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

    當一個函數建立後,它的作用域鍊會被建立此函數的作用域中可通路的資料對象填充,例如定義下面這樣一個函數: 

在函數add建立時,它的作用域鍊中會填入一個全局對象,該對象包含了所有全局變量,如下圖所示:

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

函數add的作用域将會在執行時候用到,例如執行如下代碼:

    執行此函數時會建立一個稱為“運作期上下文(execution context)”的内部對象,運作期上下文定義了函數執行時的環境。每個運作期上下文都有自己的作用域鍊,用于辨別符解析,當運作期上下文被建立時,而它的作用域鍊初始化為目前運作函數的[[scope]]所包含的對象。

   

    這些值按照它們出現在函數中的順序被複制到運作期上下文的作用域鍊中。它們共同組成了一個新的對象,叫“活動對象(activation object)”,該對象包含了函數的所有局部變量、命名參數、參數集合以及this,然後此對象會被推入作用域鍊的前端,當運作期上下文被銷毀,活動對象也随之銷毀。新的作用域鍊如下圖所示:

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

    在函數執行過程中,沒遇到一個變量,都會經曆一次辨別符解析過程以決定從哪裡擷取和存儲資料。該過程從作用域鍊頭部,也就是從活動對象開始搜尋,查找同名的辨別符,如果找到了就使用這個辨別符對應的變量,如果沒找到繼續搜尋作用域鍊中的下一個對象,如果搜尋完所有對象都未找到,則認為該辨別符未定義。

了解javascript作用域和作用域鍊        作用域    作用域鍊     總結

  根據上述講的作用域鍊的結構可以看出,定義的辨別符的越深,那麼讀寫的速度也就越慢,而全局變量總是處于作用域鍊的最末端,是以當變量解析的時候,查找全局變量是最慢的,是以在編寫代碼的時候要盡可能少的使用全局變量,盡可能使用局部變量。

繼續閱讀