標籤:機制 函數調用 ret 記憶體 其他 儲存 bsp 聯絡 開始
幀:一個幀是一個連續的工作單元。當一個js函數被調用時,運行時環境就會在棧中建立一個幀。幀裡儲存了特殊的函數參數和局部變數。當函數返回時,幀就被從棧中推出。例如:
function foo(b) { var a = 10; return a + b + 6;}function bar(x) { var c = 4; return foo(c * x);}
在聲明了foo和bar函數後,執行bar函數
bar(20)
當bar被執行時,運行時將會建立一個包含bar 的參數和所有局部變數的幀。這個幀被添加到了棧的頂部。
bar函數在內部調用了foo的函數,當foo函數被調用時,棧的頂部就又建立了一個新的幀。當foo函數執行完畢後,棧頂部對應的幀就被移除。當bar函數執行完畢後,相應的幀同樣被移除。
如果foo函數中又調用了bar函數,那麼就建立了一個無限迴圈的函數調用,就會導致棧被填滿最後拋出錯誤。
棧:棧包含了一個資訊在執行時的所有步驟(幀)。棧的資料結構為“後進先出”,因此當一個幀被加入到一個棧中時,它總是被添加到最上面,事件迴圈會從上至下地處理棧中的幀。
隊列:
隊列中包含一個待執行資訊的列表,每一個資訊都與一個函數相互聯絡。當棧為空白時,隊列中的一條資訊就會被取出並處理。處理過程為調用該資訊所關聯的函數,然後將此幀添加到棧的頂部。當棧在此為空白時,本次資訊處理視為結束。
堆:
堆是一個記憶體儲存空間,它不關注內部儲存的內容的儲存順序,堆中儲存了所有正在被使用的變數和對象。同時也儲存了一些當前範圍已經不會再被用的但還沒被記憶體回收機制回收的幀。
事件迴圈:
事件迴圈內的資訊是線性執行的,這意味著它接收到一個資訊後,在處理完畢之前,不會再處理其他任何資訊。如果棧是空的,那麼函數就會立刻執行。當所有的幀被加入棧中後,棧便開始從上至下清除這些幀。最後,棧會被清空,然後下一個資訊將會被處理。
理解js運行時的一些概念