1 閉包的含義
1.1MDN上對(duì)閉包的解釋
函數(shù)和對(duì)其周圍狀態(tài)(lexical environment,詞法環(huán)境)的引用捆綁在一起構(gòu)成閉包(closure)。也就是說(shuō)车酣,閉包可以讓你從內(nèi)部函數(shù)訪問(wèn)外部函數(shù)作用域外遇。在 JavaScript 中,每當(dāng)函數(shù)被創(chuàng)建女阀,就會(huì)在函數(shù)生成時(shí)生成閉包宅荤。
1.2我對(duì)閉包的理解
每個(gè)函數(shù)都是一個(gè)閉包屑迂,函數(shù)F()在其私有空間定義的變量在函數(shù)空間外是不可見(jiàn)的,由于F()是可以在全局空間中被調(diào)用的冯键,所以在函數(shù)中新定義并返回一個(gè)新的Inner()函數(shù)惹盼,用來(lái)返回F()的的私有變量,從而生成一個(gè)可以訪問(wèn)F()私有空間的新的全局函數(shù)惫确。
下面是一個(gè)簡(jiǎn)單的閉包的例子:
function F(param) {
? ? var N = function() {
? ? ? ? return param;
? ? }
? ? param++;
? ? return N;
}
>var inner = F(123)
>inner();
124
inner()返回的是遞增更新之后的值手报,由此可以看出,函數(shù)所綁定的是作用域本身改化,而不是一個(gè)值掩蛤。
2 常見(jiàn)的閉包錯(cuò)誤
2.1 錯(cuò)誤代碼
function F() {
? ? var arr = [], i;
? ? for (i = 0; i < 3; i++) {
? ? ? ? arr[i] = function () {
? ? ? ? ? ? return i;
????????};
????}
? ? return arr;
}
> var arr = F();
>arr[0] () ; ?>arr[1] () ;?>arr[2] () ;
3 3 3
這并不是我們想要的結(jié)果,因?yàn)槲覀冊(cè)谶@里創(chuàng)建了三個(gè)閉包所袁,它們都指向了一個(gè)共同的局部變量i盏档,但是閉包并不會(huì)記錄它們的值,它們所擁有的只是相關(guān)域在創(chuàng)建時(shí)的一個(gè)連接(即引用)燥爷。
2.2 正確代碼:
方法一:即時(shí)函數(shù)
function F() {
? ? var arr = [], i;
? ? for( i = 0; i < 3; i++) {
? ? ? ? arr[i] = (function (x) {
? ? ? ? ? ? return function () {
? ? ? ? ? ? ? ? return x;
? ? ? ? ? ? }
? ? ? ? }(i));
? ? }
? ? return arr;
}
在這里蜈亩,不再創(chuàng)建一個(gè)返回i的函數(shù)了,而是將i 傳遞給了另一個(gè)即時(shí)函數(shù)前翎,在該函數(shù)中稚配,i被賦值給了局部變量x,這樣一來(lái)港华,每次迭代中的x就會(huì)擁有各種不同的值了道川。
方法二:普通內(nèi)部函數(shù)
function F() {
? ? function binder(x) {
? ? ? ? return function() {
? ? ? ? ? ? return x;
? ? ? ? };
????}
????var arr = [], i ;
? ? for (i = 0; i < 3; i++) {
? ? ? ? arr[i] = binder(i);
? ? }
? ? return arr;
}
該方法是在每次迭代過(guò)程中,在中間函數(shù)內(nèi)將i的值本地化立宜。
3 閉包的應(yīng)用
3.1 getter與setter
假設(shè)現(xiàn)在有一個(gè)變量冒萄,表示某個(gè)特定區(qū)間內(nèi)的值,我們不想把它暴露給外部橙数,所以將它保護(hù)在相關(guān)函數(shù)的內(nèi)部尊流,然后引入兩個(gè)額外的函數(shù)——一個(gè)用于獲取變量值,另一個(gè)用于給變量重新賦值灯帮。
3.2 迭代器
function setup(x) {
? ? var i = 0;
? ? return function() {
? ? ? ? return x[i++];
? ? };
}
> var next = setup(['a','b','c']);
>next();
3.3回調(diào)
function changeSize(size){
????return function(){ document.body.style.fontSize = size + 'px'; };
}
var size12 = changeSize(12);
var size14 = changeSize(20);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-20').onclick = size14;
作為一個(gè)回調(diào)(事件觸發(fā)時(shí)調(diào)用的函數(shù))綁定到事件崖技。
參考:JavaScript面向?qū)ο缶幊讨改希ǖ诙妫?/p>