Closure 閉包

Node.js 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();

箭頭函式閉包內的 this 變數

箭頭函式當中的 this 綁定的是是定義時的物件,而不是使用時的物件,所以定義當下 this 指的是哪個物件就會是那個物件,不會隨著時間改變

所以閉包內的還是能夠存取到 this.color 的資料為定義他的 myCar.color = Blue

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();

參考資料