閉包(Closure)
函式記得並存取語彙範疇的能力,將外層變數「包」在內層暫存、使用的方式,就是所謂的「閉包」。每一個閉包保存的都是一個獨立的環境。
閉包有兩個特點。
1.變數資料存在於的 Local Scope(函式) 裡,讓外部環境無法直接存取,以確保不被污染。
2.即便這個變數所在的執行環境已經結束,其它函式執行時可以找到它所需的變數。
e.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | function getSellTicketClosure(){   var counter = 0;   function action(buyer){     counter +=1;     console.log(`(Total Sold: ${counter}) Buyer: ${buyer}`);   }   return action; }
  // 建立 closure var sellTicket = getSellTicketClosure();
  sellTicket('OneJar');          // (Total Sold: 1) Buyer: OneJar sellTicket('Tony Stark');      // (Total Sold: 2) Buyer: Tony Stark sellTicket('Steven Rogers');   // (Total Sold: 3) Buyer: Steven Rogers
  | 
 
- 在 getSellTicketClosure() 建立 counter 變數,不被 function 外的環境取用。  
 
- 在 getSellTicketClosure() 建立,取用 counter 變數的內部函式 action(),運用了函式作用域性質:內部函式可以使用父函式的變數(作用域鍊)。  
 
- 將 action() 的函數物件回傳(return)出去給 Global 環境,宣告一個 sellTicket 負責承接。  
 
- sellTicket 是一個函數物件,也形成一個閉包。
 
每一次呼叫閉包,都是建立一個新的函數執行環境。各自獨立,不會互相影響。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | function getSellTicketClosure(){   var counter = 0;   function action(buyer){     counter +=1;     console.log(`(Total Sold: ${counter}) Buyer: ${buyer}`);   }   return action; }
  var sellTicket1 = getSellTicketClosure(); sellTicket1('OneJar');            // (Total Sold: 1) Buyer: OneJar sellTicket1('Tony Stark');        // (Total Sold: 2) Buyer: Tony Stark sellTicket1('Steven Rogers');     // (Total Sold: 3) Buyer: Steven Rogers
  var sellTicket2 = getSellTicketClosure(); sellTicket2('Luffy');             // (Total Sold: 1) Buyer: Luffy sellTicket2('Nami');              // (Total Sold: 2) Buyer: Nami
  | 
 
可以用立即函式(IIFE)簡化語法
1 2 3 4 5 6 7 8 9 10 11
   | var sellTicket = (function(){   var counter = 0;   return function(buyer){     counter +=1;     console.log(`(Total Sold: ${counter}) Buyer: ${buyer}`);   } })();
  sellTicket('OneJar');            // (Total Sold: 1) Buyer: OneJar sellTicket('Tony Stark');        // (Total Sold: 2) Buyer: Tony Stark sellTicket('Steven Rogers');     // (Total Sold: 3) Buyer: Steven Rogers
  | 
 
e.g.
另一個簡單範例
1 2 3 4 5 6 7 8 9 10 11
   | function foo() {   var a = 2;   function bar() {     console.log(a);   }   return bar; }
  var baz = foo();
  baz(); // 2
  | 
 
參考:
https://ithelp.ithome.com.tw/articles/10209465
https://www.fooish.com/javascript/function-closure.html
https://blog.techbridge.cc/2018/12/08/javascript-closure/