本篇文章帶給大家關於JavaScript中區塊級作用域的實作原理相關知識,在ES6之前,區塊級作用域是不被JavaScript所支援的,JavaScript是透過什麼支援了區塊級作用域的呢?本文將講解塊級作用域的底層實現原理,希望對大家有幫助。
很多人覺得作用域與執行上下文是一個概念,這種想法是完全錯誤的!
作用域在函數宣告時就已經確定了,作用域是據名稱來找出變數的一套規則,也就是確定了目前執行程式碼對變數的存取權限。 JavaScript一共支援三種類型的作用域,它們分別是:全域作用域、函數作用域、區塊層級作用域。
執行上下文是js引擎從解釋到運行中間預編譯時對執行做的準備工作,創建了當前區域的執行環境,這個執行環境就是執行上下文。
呼叫堆疊用來裝js程式碼中的各種執行上下文,是js引擎追蹤函數執行的一個機制。
以下面的程式碼為例:
console.log(1); function pFn() { console.log(2); (function cFn() { console.log(3); }()); console.log(4); } pFn(); console.log(5); //输出:1 2 3 4 5
先有全域環境下的執行上下文,呼叫pFn後將函數環境pFn的執行上下文壓入堆疊中,由於pFn中執行了cFn函數,所以繼續壓入cFn函數的執行上下文,執行完畢後依序出棧。
全域上下文只有應用程式退出前才會被銷毀,例如關閉網頁或退出瀏覽器
我們知道在js中由於初始設計的不規範,用var關鍵字定義變數會導致變數提升等一系列問題,但為了保持相容性,我們也不得不對var宣告變數保留支持,那麼:JavaScript是如何做到既要支援變數提升,又要支援區塊級作用域的呢?
我們以下面這段程式碼為例:
function foo() { var a = 1; let b = 2; { let b = 3; var c = 4; let d = 5; console.log(a); console.log(b); } console.log(b); console.log(c); console.log(d); }
首先函數內部透過var宣告的變數被存放到變數環境中,透過let宣告的變數在預編譯階段被存放到詞法環境中,當然在函數體內部塊作用域中let宣告的變數並沒有被存放到詞法環境。
繼續執行程式碼,當執行到程式碼區塊裡面時,變數環境中的a的值已經設定為1,詞法環境中b的值已經設定成了2,注意用let宣告的變數b和d此時不是underfined而是uninitialized未初始化
#最後當函數體內區塊作用域執行結束之後,其內部變量就會從詞法環境的棧頂彈出
#我們可以知道上面問題的答案:
用let 宣告出來的變數中都會在詞法環境中存放,塊級作用域是透過詞法環境的堆疊結構來實現的,而變數提升是透過變數環境來實現的,兩者結合同時支援變數提升和區塊級作用域
以及變數的查找方式:
從詞法環境的作用域堆疊頂開始向下查找,如果找到了就回傳值,如果找不到,就繼續去變數環境中找
相關推薦:javascript學習教學
以上是JavaScript塊級作用域的實作原理(圖文詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!