JavaScript變量可以屬于本地作用域或全局作用域。
可以使用閉包將全局變量設(shè)為局部(私有)。
假設(shè)我們要使用一個(gè)變量來(lái)計(jì)數(shù)某物,并且希望該計(jì)數(shù)器可用于所有函數(shù)。
我們可以使用一個(gè)全局變量和一個(gè)增加計(jì)數(shù)器的函數(shù):
// 初始化計(jì)數(shù)器 var counter = 0; // 遞增計(jì)數(shù)器函數(shù) function increment() { counter++; } // 調(diào)用increment() 3次 increment(); increment(); increment(); // 現(xiàn)在該計(jì)數(shù)器應(yīng)為3 document.getElementById("output").innerHTML = `計(jì)數(shù)器: ${counter}`;測(cè)試看看?/?
上面的解決方案存在一個(gè)問(wèn)題:頁(yè)面上的任何代碼都可以更改計(jì)數(shù)器,而無(wú)需調(diào)用increment()。
JavaScript內(nèi)部函數(shù)可以解決此問(wèn)題。
JavaScript支持嵌套函數(shù)。嵌套函數(shù)可以訪問(wèn)其上方的范圍。
在此示例中,內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)中的計(jì)數(shù)器變量:
function outer() { var counter = 0; function inner() { counter++; } return counter; }測(cè)試看看?/?
嵌套函數(shù)可以解決前面的問(wèn)題,如果我們可以從外部訪問(wèn)inner()函數(shù)。
我們還需要找到只執(zhí)行一次counter = 0的方法,那就是下面講到的閉包。
閉包是函數(shù)和聲明該函數(shù)的詞法環(huán)境的組合。
閉包可以從另一個(gè)函數(shù)的作用域訪問(wèn)變量。這是通過(guò)在函數(shù)內(nèi)部創(chuàng)建函數(shù)來(lái)實(shí)現(xiàn)的。當(dāng)然,外部函數(shù)無(wú)法訪問(wèn)內(nèi)部作用域。
var increment = (function() { var counter = 0; function inner() { return ++counter; } return inner; })();測(cè)試看看?/?
為變量增量分配了自執(zhí)行函數(shù)的返回值。
自執(zhí)行功能僅運(yùn)行一次。它將計(jì)數(shù)器設(shè)置為零,并返回函數(shù)表達(dá)式。
閉包是即使父函數(shù)已關(guān)閉,也可以訪問(wèn)父作用域的函數(shù)。