先寫段代碼舉例
var aa = '1'
function bb() {
console.log(aa)
}
上面代碼就是一個閉包昼伴。
如果一個函數(shù),使用了它范圍外的變量监透,那么(這個函數(shù)+這個變量)就叫做閉包
閉包的兩大好處:
- 一個可以讀取函數(shù)內(nèi)部的變量
- 另一個就是讓這些變量的值始終保持在內(nèi)存中
閉包一般伴隨著函數(shù)嵌套避凝,有時候要得到函數(shù)內(nèi)的局部變量社痛,就需要在函數(shù)內(nèi)部再定義一個函數(shù)
1.讀取函數(shù)內(nèi)部的變量
function f1() {
var n = 100;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 100
上面代碼中,f2
被嵌套在f1
內(nèi)部水醋,f1
的全部變量旗笔,f2
都是可以訪問的。但是反過來不行拄踪。所有我們可以把f2
作為返回值蝇恶,這樣f1
就可以訪問了。
2.變量的值始終保持在內(nèi)存中
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
f2
是一個嵌套函數(shù)的閉包宫蛆,執(zhí)行了兩次艘包,第一次值是999,第二次是1000.證明了函數(shù)f1
的局部變量n
一直保存在內(nèi)存中耀盗,沒有在f1
調用后清除想虎。
因為 f1
是f2
的父函數(shù),f2
被賦給了一個全局變量n
叛拷,導致f2
一直在內(nèi)存中舌厨,因為f2
在f1
中,故f1
也在內(nèi)存中忿薇。(內(nèi)存回收是沒有任何地方用到這個變量或者函數(shù)裙椭,那么就被回收)躏哩。
其中nAdd
沒有用var
定義,是個全局變量揉燃。nAdd
后面的函數(shù)是匿名函數(shù)也是一個閉包扫尺,nAdd
相當于一個setter
,可以在函數(shù)外部對函數(shù)內(nèi)部的局部變量進行操作炊汤。
兩個例子
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
console.log(object.getNameFunc()()); //The Window
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
console.log(object.getNameFunc()()); //My Object
參考文檔:
1.https://zhuanlan.zhihu.com/p/22465092
2.http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html