只有函式執行時,才會創建一個新的臨時執行環境。這個環境會在函式 return (結束) 後立即銷毀,從堆疊上移除 (除非閉包機制將其部分記憶體保留在堆積上)。
建立環境兩階段
創建階段 (Creation Phase)
(待新增)
執行階段 (Execute Phase)
(待新增)
堆疊 (Stack) 是結構化的,它知道每個函式佔用多少空間,並且嚴格按照 LIFO 順序管理。
堆積 (Heap) 是非結構化的,因為它要儲存各種大小不一、壽命不定的數據,彼此之間沒有嚴格的順序關係。
這是 JS 引擎用來管理函式呼叫順序的機制。
運作方式:當程式執行時,每次呼叫一個函式,就會將該函式相關的資訊(稱為堆疊框,stack frame)推入堆疊的最頂端。
後進先出 (LIFO):由於函式是後進先出 (Last-In-First-Out) 的原則,最後被呼叫的函式會最先執行完畢。當一個函式執行完畢後,它的堆疊框會從堆疊中移除,程式會回到呼叫它的那個函式繼續執行。
Javascript 是一種「單執行續 (single-thread)」的語言,意思就是一次只能做一件事情,如果安排了很多事情要給他做,他就會讓這些事情去排隊,再一件一件做。
最後進來的,最先出去 (Last-In, First-Out)。
堆疊就是用這個原則來管理函式:最後被呼叫的函式,必須先執行完畢並退出,才能執行底下的函式。
這是用於長期、非結構化儲存的區域。
長期:所有的物件 (Objects)、陣列 (Arrays)、函式定義,以及閉包物件本身,都儲存在堆積上。
非結構化:數據不是按照嚴格的 LIFO 順序管理,而是以分散的方式儲存複雜物件。
概念:指一個函式能夠持續存取其外部作用域變數的現象。這是我們在程式碼中討論的抽象行為。
實作:指JS引擎在堆積(Heap)上創建出來、用來物理性地儲存那些被記住的外部變數的數據結構。
是堆積上的一個物件,讓一個已經被銷毀的執行環境,(堆疊)中的變數,仍然能被外部的函式(也在堆積上)存取。
雙層/多層函式:閉包可以發生在兩層、三層甚至更多層的函式中,只要內層函式參考了它任何外層的變數。
物件內的函式:如果一個物件的方法 (method) 引用了該物件構造函式(如 class)中的私有變數,它也會形成閉包。
函式內的物件:函式回傳一個物件時,該物件只是在堆積上有一個外部引用。雖然它也不會被回收,但它沒有保留外部函式的作用域,就不會形成閉包。
當我們說 閉包 時,我們談論的是行為;
當我們說 閉包物件 時,我們談論的是讓這個行為得以發生的記憶體容器。兩者是一體的。