- 需要掌握才能理解語言的複雜細節。
- 不像我們創建數組或函數那樣創建。
- 一個 fn 傳回另一個儲存在 LHS 變數中的 fn。
雷雷
- secureBooking fn 在全域範圍內執行。
- 將在全域執行上下文上建立一個新的執行上下文。
- 每個執行上下文(EC)都有自己的變數環境及其所有變數。 'let PassengerCount = 0' 在此 EC 內定義。 它可以存取其父作用域的所有變數。
- 傳回一個新的fn,並將其儲存在booker中。
- 全域 EC 也將包含 booker 變數。
- 現在 secureBooking() 將從 EC 中刪除並消失。 secureBooking EC 環境不再活躍。但仍正在存取在建立 fn 時定義的 PassengerCount 變數。
- 不過,內部 fn 將能夠存取外部 fn 內部定義的 PassengerCount 變數。這是由於關閉而發生的。
- 閉包讓 fn 記住圍繞 fn 的誕生地或其 EC 定義的變數。
- booker 不是 fn,位於全域範圍內。
- 現在執行booker();第一次將在呼叫堆疊上建立一個 EC,並具有自己的變數。
- fn 可以存取建立 fn 的執行上下文的變數環境。安全預訂。因此,booker 將有權存取 secureBooking fn 變數環境中定義的變數。即使包含 fn 的 secureBooking fn 的 EC 已從呼叫堆疊中彈出,fn 的誕生地(即定義)與其周圍變數環境的這種連接也稱為閉包。
- 閉包:附加到 fn 的變數環境,與建立 fn 時和地點完全相同。
- 作用域鏈在閉包期間被保留,即使 EC 消失了,可變環境仍然以某種方式存在於引擎中。因此,我們說 booker fn 對父 fn 是封閉的,包括我們這裡沒有的父 fn 參數。
- 使用閉包,fn 不會失去與其出生地周圍定義的變數的連結。
- 如果變數不在目前作用域內,JS 會在尋找作用域鏈之前先檢查閉包。假設如果有一個全域變量,即使這樣,也會先尋找其閉包中定義的變數。
- 閉包優先於作用域鏈。
- 第一次執行 booker() 後,passengerCount 的值會增加,登入控制台,然後 booker 從呼叫堆疊中彈出。
- 執行移動到下一行,建立新的 EC,但閉包變數仍然存在。現有值增加並彈出 EC。
- 這個過程第三次重複。
概括
Defn:閉包是創建 fn 的 EC 的封閉變數環境,即使在該 EC 消失之後也是如此。
此外,閉包允許 fn 存取其父 fn 的所有變量,即使在父 fn 返回之後也是如此。 fn 保留其外部作用域的引用,因此始終保留作用域鏈。
閉包確保 fn 不會失去與 fn 誕生時存在的變數的連結。它就像一個 fn 隨身攜帶的背包。這個背包具有創建 fn 的環境中存在的所有變數。
我們不必手動建立閉包。此外,我們甚至無法明確存取封閉變數。閉包不是有形的 JS 對象,即我們無法存取閉包並從中獲取變數。它是 fn 的內部屬性。要查看背包,「console.dir(booker);」
[[Scope]] 將向您展示此 fn 呼叫的 VE。
[[]] 表示它是一個內部屬性,我們無法從程式碼中存取它。
我們總是不需要從另一個 fn 回傳一個 fn 來建立閉包。在下面的範例中,變數「f」甚至沒有在 fn 內定義,因為它在全域範圍內。即使在 g() 完成其 EC 之後,它也能夠存取“a”變數。 ‘a’現在在‘f’的背包裡。
雷雷
- setTimeout(callbackFnToBeCalled, 延遲);
- 閉包變數比作用域鏈具有更高的優先權。
雷雷
以上是揭秘 JS 中的閉包的詳細內容。更多資訊請關注PHP中文網其他相關文章!