Closure 閉包
Node.js Closure 閉包
		
		Categories:
什麼是 Closure ?
- 當你有個 想保護起來的狀態,但又會不停地修改該狀態,就可以使用閉包回傳指定的修改方法,所以閉包接收的就是一個 function 內容。
- 一般 function 執行完之後,裡面的資源就會全部被釋放掉( 垃圾回收機制 ),而 Closure 可以保存著裡面的狀態
若資源不釋放可能會造成 memory leak 問題,要注意
Closure 的好處
- 可以保存狀態
- 不需要用到容易污染的全域變數,也可以讓外部修改到狀態。
閉包是個 捕捉了外部函式變數(或使之繼續存活)的函式
const foo = () => {
  let name = 'hi';
  // closure 閉包函式
  const bar = () => {
    // 使用外層變數
    // KJ
    console.log(name);
  }
  bar();
}
foo();
基本上函式離開執行環境時,也會同時將佔用的記憶體空間給釋放出來。
例如以上 name 變數 應該在執行完畢就會在 memory (記憶體) 中被清掉。
但因為 closure 特性此 name 變數 還會繼續被保留
運用 closure 特性讓變數可以一直被保留並且做運算
var storyWriter = function(){
   var story = "";
   var addWords = function(string){
       story = story + string
       return story.trim();
   }
   var erase = function(){
       story = "";
   }
   return {
       addWords: addWords,
       erase: erase
   }
}
let writer = storyWriter();
writer.addWords('444');
writer.addWords('555');
let words = writer.addWords('666');
// 444555666
console.log(words);
取用變數範圍
const globalVariable = `global variable`;
const outerFunc = (outerParam) => {
   const outerVariable = `outer variable`;
   let innerFunc = (innerParam) => {
       const innerVariable = `inner variable`;
       // 可取用全域變數
       console.log(`[inner] globalVariable: ${globalVariable}`)
       // 可取用外層變數
       console.log(`[inner] outerVariable: ${outerVariable}`)
       // 可取用本身變數
       console.log(`[inner] innerVariable: ${innerVariable}`)
       // 可取用外層參數
       console.log(`[inner] outerParam: ${outerParam}`);
       // 可取用本身參數
       console.log(`[inner] innerParam: ${innerParam}`);
   }
   // 呼叫內部函式
   innerFunc(`inner param`);
   // 可取用全域變數
   console.log(`<outer> globalVariable: ${globalVariable}`)
   // 可取用本身變數
   console.log(`<outer> outerVariable: ${outerVariable}`)
   // 可取用本身參數
   console.log(`<outer> outerParam: ${outerParam}`);
}
outerFunc(`outer param`);
// [inner] globalVariable: global variable
// [inner] outerVariable: outer variable
// [inner] innerVariable: inner variable
// [inner] outerParam: outer param
// [inner] innerParam: inner param
// <outer> globalVariable: global variable
// <outer> outerVariable: outer variable
// <outer> outerParam: outer param
閉包內的 this 變數
var myCar = {
   color: `Blue`,
   logColor: function() {
       var self = this;
       // In logColor — this.color: Blue
       console.log(`In logColor — this.color: ` + this.color);
       // In logColor — self.color: Blue
       console.log(`In logColor — self.color: ` + self.color);
       (function() {
           // In IIFE — this.color: undefined
           console.log(`In IIFE — this.color: ` + this.color);
           // In IIFE — self.color: Blue
           console.log(`In IIFE — self.color: ` + self.color)}
       )()
   },
}
myCar.logColor();
函數用新寫法會變成不是
undefined????
var myCar = {
   color: `Blue`,
   logColor: function() {
       var self = this;
       // In logColor — this.color: Blue
       console.log(`In logColor — this.color: ` + this.color);
       // In logColor — self.color: Blue
       console.log(`In logColor — self.color: ` + self.color);
       (() => {
           // In IIFE — this.color: Blue
           console.log(`In IIFE — this.color: ` + this.color);
           // In IIFE — self.color: Blue
           console.log(`In IIFE — self.color: ` + self.color)}
       )()
   },
}
myCar.logColor();
Closure 應用
快取,拿來避免重複的運算
// 假設 complex 要花費很多時間
function complex(num) {
    console.log('caculating');
    return num * num * num;
}
function Cache(func) {
    let ans = {};
    return function (num) {
        if (ans[num]) {
            // ans 有存過,直接回傳
            return ans[num];
        }
        // 沒存過,丟入 ans 並回傳
        return ans[num] = func(num);
    }
}
const CachedComplex = Cache(complex);
// 'caculating',1000 => 跑運算結果
console.log(CachedComplex(10));
// 1000 => 直接拿值
console.log(CachedComplex(10));
// 1000 => 直接拿值
console.log(CachedComplex(10));