前言:
閉包(closure)是Javascript語言的一個難點,也是它的特點,不少高級應用都要依靠閉包實現。
要理解閉包,首先必須理解Javascript特殊的變量做用域。
變量的做用域無非就是兩種:全局變量和局部變量。
Javascript語言的特殊之處,就在於函數內部能夠直接讀取全局變量。
1. 關於全局變量 和 局部變量的 理解:
函數外面: var a = 20; 此處var聲明的a是一個全局變量
函數內部:function getAll() {
//若是是 var 聲明的,則是局部變量 (與函數外面聲明的相反 )
var a = 20;
//若是是直接寫的(省去var聲明的),則是全局變量
a = 20
}
訪問範圍:
全局變量,在整個script中,均可以訪問到;
可是局部變量只能在函數內部訪問到;函數外部是不能訪問到的。
有時候,想要在全局訪問到函數內部的局部變量,要怎麼辦?
——閉包,能夠實現這一點。
2. 閉包(closure):
何爲閉包?
在一個函數中寫入另一個函數,而且能夠訪問到這個函數的局部變量的函數,這就是閉包。
在js中,只有一個函數內部的子函數才能夠讀取局部變量,因此,也能夠把閉包理解爲「定義在一個函數內部的函數」。
(本質上,閉包就是講函數內部和函數外部連接的一座橋樑。)
function fn1(){
var a = 20;
return function fn2(){
alert(a);
}
}
fn1()();
此處的 fn2函數就是閉包函數。
3. 閉包的做用:
第一:能夠讀取一個函數內部的函數,
第二:避免「垃圾回收機制」回收,由於子函數會返回一個全局變量,又會調用父函數的局部變量,兩個變量相互調用;
因此,兩個函數都不會被清除。
四、關於閉包中this的指向問題( 進階版)。
代碼一:
var name = 'The window ';
var object = {
name: ' my object',
fn1 : function(){
alert('1' + this.name); //此處this.name爲 my object (由於會繼承object)
return function(){
alert('2' + this.name); //此處this.name爲The window (沒有執行是上下文,因此,找到了windows )
return this.name;
}
}
}
object.fn1()();
難點:紅色部分打印出來的爲何是「The window」 ?
解釋:
咱們能夠換種寫法:
var obj = object.fn1()();
obj();
這裏的obj()是函數體 function() { return this.name };
此處的obj指向的是window,因此this.name是The.window
代碼二:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
alert(that.name); //?
return function(){
alert(this.name); //?
alert(that.name); //?
return that.name;
};
}
};
object.getNameFunc()();
解釋:這裏只要是that.name都是指向的「My Object」;
由於,紅色的那行代碼,把this的指向作了保存。
可是若是用的是,this.name依然指向的是windows(能夠參考代碼一中的解釋)。