1、概念:閉包是詞法閉包的的簡稱,是引用了自由變量的函數(shù)水醋。這個被引用的自由變量和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造他的環(huán)境也不例外彪置。另一種說法拄踪,閉包是由函數(shù)和其相關(guān)的環(huán)境組成的實(shí)體
(1)在js中一個函數(shù)在另一個函數(shù)中定義,可以訪問到父函數(shù)的成員悉稠,內(nèi)部的函數(shù)就稱為閉包函數(shù)
(2)
解釋:閉包是詞法閉包的的簡稱宫蛆,是引用了自由變量的函數(shù)
function f1(){
var a=10;
var b=20;
function f2(){
console.log(a);
};
f2();
}
f1();
結(jié)果是:
查看閉包是
var a=10;
var b=20;
function f2(){}
引用的函數(shù)指的是f2() ,引用的自由變量是父函數(shù)的自由變量 a b
解釋:即使已經(jīng)離開了創(chuàng)造他的環(huán)境也不例外的猛。
function f1(){
var a=10;
var b=20;
return function f2(){
console.log(a);
};
}
var result=f1();
restult()
結(jié)果是:
var a=10;
var b=20;
f2()離開了f1的作用域仍然能夠?qū)崿F(xiàn)訪問ab耀盗,就是f2的scope作用域在f1的詞法環(huán)境外面,仍然能夠訪問f1內(nèi)部的詞法環(huán)境
2卦尊、閉包特點(diǎn)
(1)閉包作為與函數(shù)成對的數(shù)據(jù)叛拷,在函數(shù)執(zhí)行過程中屬于激活狀態(tài)脏嚷,
(2)閉包運(yùn)行結(jié)束后株依,保持運(yùn)行過程中的最終數(shù)據(jù)狀態(tài)
函數(shù)閉包的目的:閉包的函數(shù)如何訪問數(shù)據(jù)(作用域可見性)房待,以及閉包內(nèi)的數(shù)據(jù)如何銷毀(數(shù)據(jù)引用識別)
3踪古、兩種表示
(1)閉包是一個對象九串,對象里有一個函數(shù)亭畜,以及被這個函數(shù)封閉捕獲的變量循集。
(2)閉包是一種函數(shù)掸哑,與這個函數(shù)相關(guān)聯(lián)的還有捕獲變量的環(huán)境
4扫尺、閉包的好處
(1)減少全局變量
function add(){
var a=0;
a++;
return a;
}
調(diào)用一次:add();//返回結(jié)果是1
在調(diào)用一次:add();//返回結(jié)果依然是1
因?yàn)閍在函數(shù)中是局部變量筋栋,每次都被初始化,如果要實(shí)現(xiàn)1,2,3的效果需要把a(bǔ)放到外面進(jìn)行全局變量
閉包可以實(shí)現(xiàn)避免全局變量
function add(){
var a=0;
return function(){ //不管有沒有return都能實(shí)現(xiàn)閉包正驻,匿名函數(shù)
a++;
alert(a);
}
};
var result=add();//add()函數(shù)返回一個匿名函數(shù)弊攘,這個函數(shù)保留了a的詞法環(huán)境抢腐,即一個閉包,所以在調(diào)用的時候a的值從0開始
result();//返回1
result();//返回2
(2)減少參數(shù)傳遞數(shù)量
function calFactory(base){
//這里面也是一個閉包襟交,下面的匿名函數(shù)詞法環(huán)境包括base迈倍,引用內(nèi)部成員變量和內(nèi)部成員函數(shù),形成一個閉包
return function(max){
var total=0;
for(var i=0;i<=max;i+=){
total+=i;
}
return total+base;
}
}
調(diào)用
var adder=calFactory(2); //calFactory每調(diào)用一次都會產(chǎn)生一個新的閉包
alert(adder(3))//返回結(jié)果為8
alert(adder(2))//返回結(jié)果為5
(3)封裝的作用
(functon (){
var m=0;
function getM(){ //
return m
};
function setM(value){
m=value
};
window.g=getM; //返回到window上
window.s=setM; //返回到window上
})();
s(12);
alert(g());//12
5捣域、閉包的注意點(diǎn)
(1)如果閉包捕獲父環(huán)境中的變量啼染,只是引用,不是復(fù)制
(2)父函數(shù)每次調(diào)用會產(chǎn)生不同的閉包
(3)循環(huán)的時候會出現(xiàn)的問題
<body>
<div id="1">1</div>
<div id="2">2</div>
<div id="3">3</div>
</body>
for(var i=1;i++;i<=3){
var ele=document.getElementById(i);
ele.onclick=function(){
alert(i) ;
}
}
//彈出的都是
//此時產(chǎn)生的問題是竟宋,由于javascript沒有塊級作用域提完,所以,var i把i做成了一個全局變量丘侠,當(dāng)產(chǎn)生ele的時候徒欣,循環(huán)時,都產(chǎn)生了三個元素蜗字,但是此時onclick還沒有執(zhí)行打肝,并且由于i是全局對象,當(dāng)引用的時候挪捕,i已經(jīng)變成了4
閉包實(shí)現(xiàn)方式
for(var i=1;i++;i<=3){
var ele=document.getElmentById(i);
ele.onclick=(function(id){
return function(){
alert (id)
}
})(i
);//把i傳進(jìn)去
}
//因?yàn)槭橇⒓磮?zhí)行函數(shù)粗梭,當(dāng)生成了一個ele就立即調(diào)用一次,就把i傳進(jìn)去一次级零,當(dāng)ele發(fā)生變化時断医,在立即調(diào)用函數(shù),并且閉包的調(diào)用每次會產(chǎn)生不同的閉包奏纪,i的值傳遞的都是新進(jìn)入的
//主要是立即調(diào)用函數(shù)鉴嗤,不用等待就能執(zhí)行,就能產(chǎn)生閉包