|
|
|
|
|
閉包是一個(gè)訪問(wèn)其詞法范圍的函數(shù),甚至在其詞法范圍之外執(zhí)行。
更簡(jiǎn)單地說(shuō),閉包是一個(gè)函數(shù),它從定義它的地方記住變量,而不管它后來(lái)在哪里執(zhí)行。在本文中,將通過(guò)多個(gè)示例介紹什么是閉包,及何時(shí)使用閉包。
JavaScript 閉包
在開始認(rèn)識(shí)閉包之前,你得首先了解嵌套函數(shù)。
在 JavaScript 中,一個(gè)函數(shù)可以有一個(gè)或多個(gè)內(nèi)部函數(shù)。這些嵌套函數(shù)在外部函數(shù)的范圍內(nèi)。內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)的變量和參數(shù)。但是,外部函數(shù)不能訪問(wèn)內(nèi)部函數(shù)內(nèi)部定義的變量。
function OuterFunction() {
var outerVariable = 1;
function InnerFunction() {
alert(outerVariable);
}
InnerFunction();
}
在上面的例子中,InnerFunction()
可以訪問(wèn) outerVariable
這個(gè)變量。
現(xiàn)在,根據(jù)上面的定義,InnerFunction()
可以訪問(wèn) outerVariable
變量,即使它會(huì)單獨(dú)執(zhí)行。參看以下示例。
function OuterFunction() {
var outerVariable = 100;
function InnerFunction() {
alert(outerVariable);
}
return InnerFunction;
}
var innerFunc = OuterFunction();
innerFunc(); // 100
在上面的示例中,return InnerFunction;
當(dāng)你調(diào)用 OuterFunction()
時(shí),從 OuterFunction
返回 InnerFunction
。變量innerFunc
僅引用 InnerFunction()
,而不引用 OuterFunction()
。所以現(xiàn)在,當(dāng)你調(diào)用 innerFunc()
時(shí),它仍然可以訪問(wèn)outerVariable
在 OuterFunction()
中聲明的內(nèi)容,這稱為閉包。
一個(gè)函數(shù)可以在 JavaScript 中返回另一個(gè)函數(shù),分配給變量的函數(shù)稱為函數(shù)表達(dá)式。
閉包的一個(gè)重要特征是外部變量可以在多次調(diào)用之間保持其狀態(tài)。請(qǐng)記住,內(nèi)部函數(shù)不會(huì)保留外部變量的單獨(dú)副本,而是引用外部變量,這意味著外部變量的值將會(huì)改變,如果你使用內(nèi)部函數(shù)更改它。示例:
function Counter() {
var counter = 0;
function IncreaseCounter() {
return counter += 1;
};
return IncreaseCounter;
}
var counter = Counter();
alert(counter()); // 1
alert(counter()); // 2
alert(counter()); // 3
alert(counter()); // 4
在上面的例子中,外部函數(shù)Counter
返回內(nèi)部函數(shù)IncreaseCounter()
的引用。increaseCounter
將外部變量 counter
增加到 1。所以多次調(diào)用內(nèi)部函數(shù)會(huì)使計(jì)數(shù)器每次增加一個(gè)。
閉包在多層內(nèi)部函數(shù)中是有效的。示例:
function Counter() {
var counter = 0;
setTimeout( function () {
var innerCounter = 0;
counter += 1;
alert("counter = " + counter);
setTimeout( function () {
counter += 1;
innerCounter += 1;
alert("counter = " + counter + ", innerCounter = " + innerCounter)
}, 500);
}, 1000);
};
Counter();
根據(jù)閉包的定義,如果內(nèi)部函數(shù)訪問(wèn)外部函數(shù)的變量,那么只有它被稱為閉包。
不是閉包的示例:
var Counter = (function () {
var i = 0;
return { counter : i += 1 };
})();
何時(shí)使用閉包?
閉包對(duì)于隱藏 JavaScript 中的實(shí)現(xiàn)細(xì)節(jié)很有用。換句話說(shuō),創(chuàng)建私有變量或函數(shù)可能很有用。
以下示例顯示了如何創(chuàng)建私有函數(shù)和變量:
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
alert(counter.value()); // 0
counter.increment();
counter.increment();
alert(counter.value()); // 2
counter.decrement();
alert(counter.value()); // 1
在上面的示例中,increment()
、decrement()
和 value()
成為公共函數(shù),因?yàn)樗鼈儼诜祷貙?duì)象中,而 changeBy()
函數(shù)成為私有函數(shù),因?yàn)樗环祷夭⑶覂H在內(nèi)部使用increment()
和decrement()
。
總結(jié)
本文通過(guò)多個(gè)示例,介紹了什么是閉包,以及何時(shí)使用閉包。通過(guò)本文的學(xué)習(xí),你應(yīng)該記住了閉包的一些重要特性,懂得判斷一些函數(shù)是不是閉包,不具備閉包特性的函數(shù)就不能稱之為閉包。
相關(guān)文章