function foo() {
const a = 2;
function bar() {
console.log(a);
}
return bar;
}
const baz = foo();
baz(); // 2
函數(shù) bar() 的詞法作用域能夠訪問 foo() 的內(nèi)部作用域教硫。然后我們將 bar() 函數(shù)本身當(dāng)作一個(gè)值類型進(jìn)行傳遞菩帝。在這個(gè)例子中裸卫,我們將 bar 所引用的函數(shù)對(duì)象本身當(dāng)作返回值识颊。
在 foo() 執(zhí)行后允耿,其返回值(也就是內(nèi)部的 bar() 函數(shù))賦值給變量 baz 并調(diào)用 baz()奕删,實(shí)際上只是通過不同的標(biāo)識(shí)符引用了內(nèi)部的函數(shù) bar()俺泣。
bar() 顯然可以被正常執(zhí)行。但是在這個(gè)例子中,它在自己定義的詞法作用域以外的地方執(zhí)行伏钠。
在 foo() 執(zhí)行后横漏,通常會(huì)期待 foo() 的整個(gè)內(nèi)部作用域都被銷毀,因?yàn)槲覀冎酪嬗欣厥掌饔脕?lái)釋放不再使用的內(nèi)存空間贝润。由于看上去 foo() 的內(nèi)容不會(huì)再被使用绊茧,所以很自然地會(huì)考慮對(duì)其進(jìn)行回收。
而閉包的“神奇”之處正是可以阻止這件事情的發(fā)生打掘。事實(shí)上內(nèi)部作用域依然存在华畏,因此沒有被回收。誰(shuí)在使用這個(gè)內(nèi)部作用域尊蚁?原來(lái)是 bar() 本身在使用亡笑。
拜 bar() 所聲明的位置所賜,它擁有涵蓋 foo() 內(nèi)部作用域的閉包横朋,使得該作用域能夠一直存活仑乌,以供 bar() 在之后任何時(shí)間進(jìn)行引用。
bar() 依然持有對(duì)該作用域的引用琴锭,而這個(gè)引用就叫做閉包晰甚。