首頁 > web前端 > js教程 > 主體

揭秘 JS 中的閉包

WBOY
發布: 2024-09-01 21:13:32
原創
1000 人瀏覽過

Demystifying Closures in JS

  • 需要掌握才能理解語言的複雜細節。
  • 不像我們創建數組或函數那樣創建。
  • 一個 fn 傳回另一個儲存在 LHS 變數中的 fn。
const secureBooking = function(){
  let passengerCount = 0;
  return function(){
    passengerCount++;
    console.log(`${passengerCount} passengers`);
  }
}

const booker = secureBooking();

booker();
booker();
booker();
登入後複製
  • 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’的背包裡。

let f;

const g = function(){
  const a = 23;
  f = function() {
    console.log(a*2); // 46
  };
};


const h = function(){
  const b = 777;
  f = function(){
    console.log(b*2); // 1554
  };
};

g();
f();
console.dir(f);

// f fn is reassigned using h fn. Hence, old closure value i.e 'a' will be replaced with new value 'b' which can be verified using console.dir().
h();
f();
console.dir(f);
登入後複製
  • setTimeout(callbackFnToBeCalled, 延遲);
  • 閉包變數比作用域鏈具有更高的優先權。
// Boarding Passengers using Closures
const boardPassengers = function(n, wait){
  const perGroup = n / 3;

  setTimeout(function(){
    console.log(`We are now boarding all ${n} passengers`);
    console.log(`There are 3 groups, each with ${perGroup} passengers`)
  }, wait*1000);

  console.log(`Will start boarding in ${wait} seconds`);
}

boardPassengers(180, 3);
登入後複製

以上是揭秘 JS 中的閉包的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!