閉包(Closure )在JavaScript中是一個比較深入的議題,想了解閉包的原理,得先從幾個觀念著手:
還未熟悉這些觀念的讀者,可以先從這方面著手,再來了解閉包。
到底什麼是閉包?說實話,還真是不好解釋,所以先來看範例,再從中了解。
var globalValue = 'Hello!';
function outerFun() {
console.log(globalValue);
}
outerFun(); //Hello!
很簡單的範例,結果不是重點,重點是一堆人寫過這樣的程式,卻不知道建立一個閉包。
變數globalValue與函式outerFun( )都宣告在全域執行環境(閉包)。
在這裡,閉包所代表的是全域執行環境。閉包內,outerFun( )可以存取globalValue。
再看下一個。
var globalValue = 'Hello!';
var outer;
function outerFun() {
var localValue = 'Mary';
function innerFun() {
console.log(`${globalValue} ${localValue}`);
}
outer = innerFun;
}
outerFun();
outer();
我們來分析會如何執行:
但結果:
咦!localValue還活著,明明outerFun( )的執行環境已經消失了,為何localValue沒事?
是因為閉包。
當我們在outerFun( )內建立innerFun( ),其實就是在建立閉包。
閉包內部包含了函式在定義時,它的作用域範圍能夠存取的變數,所以即便outerFun( )的執行環境消失了,閉包依舊將此變數保存於記憶體中,讓作用域範圍內的函式能夠看到它。
我們再看另一個例子。
function useCounter() {
var times = 0;
function counter() {
times++;
return times;
}
return counter;
}
var runCounter = useCounter();
console.log(runCounter()); //1
console.log(runCounter()); //2
console.log(runCounter()); //3
跟剛剛的範例差不多,只不過結果是回傳函式。
總結:
閉包讓函式可以存取函式在定義(非執行)時,其作用域範圍內的變數,它為函式及其所屬的變數架起安全網,如此一來,即使函式所屬的執行環境消失了,它仍然可以存取閉包內的變數。
參考來源:
忍者:JavaScript開發技巧探秘 第五章