這個問題的經(jīng)典性胸嘴,幾乎所有面試官都會問到這個問題,什么情況下會發(fā)生閉包斩祭,為什么需要閉包劣像,什么場景下需要,閉包閉了誰摧玫,怎么釋放被閉包的變量內(nèi)存驾讲,閉包的優(yōu)點(diǎn)是什么,缺點(diǎn)是什么等等席赂。
http://www.cnblogs.com/xxcanghai/p/4991870.html
JS中有幾種函數(shù)
具名函數(shù) (命名函數(shù))和匿名函數(shù)吮铭。
創(chuàng)建函數(shù)的幾種方式
1.聲明函數(shù)
2.創(chuàng)建匿名函數(shù)表達(dá)式
3.創(chuàng)建具名函數(shù)表達(dá)式
4.Function構(gòu)造函數(shù)(可以得到想要的結(jié)果,類似eval)
var str='2+5+8';
alert(new Function('return '+str)());
返回的結(jié)果是15颅停。
5.自執(zhí)行函數(shù)
(function(){alert(1);})();
(function fn1(){alert(1);})();
6.其他創(chuàng)建函數(shù)的方法
當(dāng)然還有其他創(chuàng)建函數(shù)或執(zhí)行函數(shù)的方法谓晌,這里不再多說,比如采用 eval 癞揉, setTimeout 纸肉, setInterval 等非常用方法,這里不做過多介紹喊熟,屬于非標(biāo)準(zhǔn)方法柏肪,這里不做過多展開。
注意:所有聲明的匿名函數(shù)都是一個新函數(shù)芥牌;
所有new出來的函數(shù)也都是一個新的函數(shù)烦味。
函數(shù)作用域鏈:
作用域:就是變量和函數(shù)的可訪問范圍,控制著變量和函數(shù)的可見性與生命周期壁拉,在JavaScript中變量的作用域有全局作用域和局部作用域谬俄。
var a=3; //全局變量
function fn(b){ //局部變量
c=2; //全局變量
var d=5; //局部變量
function subFn(){
var e=d; //父函數(shù)的局部變量對子函數(shù)可見
for(var i=0;i<3;i++){
console.write(i);
}
alert(i);//3, 在for循環(huán)內(nèi)聲明,循環(huán)外function內(nèi)仍然可見弃理,沒有塊作用域
}
}
alert(c); //在function內(nèi)聲明但不帶var修飾溃论,仍然是全局變量
預(yù)解析
JavaScript雖然是解釋執(zhí)行,但也不是按部就班逐句解釋執(zhí)行的痘昌,在真正解釋執(zhí)行之前钥勋,JavaScript解釋器會預(yù)解析代碼炬转,將變量、函數(shù)聲明部分提前解釋算灸,這就意味著我們可以在function聲明語句之前調(diào)用function返吻。
console.log(a); //undefined
var a=3;
console.log(a); //3
console.log(b); //Uncaught ReferenceError: b is not defined
執(zhí)行環(huán)境
定義了變量或函數(shù)有權(quán)訪問的其它數(shù)據(jù),決定了它們的各自行為乎婿。
全局執(zhí)行環(huán)境是最外層的一個執(zhí)行環(huán)境测僵,在web瀏覽器中全局執(zhí)行環(huán)境是window對象,因此所有全局變量和函數(shù)都是作為window對象的屬性和放大創(chuàng)建的谢翎。每個函數(shù)都有自己的執(zhí)行環(huán)境捍靠,當(dāng)執(zhí)行流進(jìn)入一個函數(shù)的時候,函數(shù)的環(huán)境會被推入一個函數(shù)棧中森逮,而在函數(shù)執(zhí)行完畢后執(zhí)行環(huán)境出棧并被銷毀榨婆,保存在其中的所有變量和函數(shù)定義隨之銷毀,控制權(quán)返回到之前的執(zhí)行環(huán)境中褒侧,全局的執(zhí)行環(huán)境在應(yīng)用程序退出(瀏覽器關(guān)閉)才會被銷毀良风。
作用域鏈:JavaScript里一切都是對象。函數(shù)對象和其它對象一樣闷供,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內(nèi)部屬性烟央。其中一個內(nèi)部屬性是[[Scope]],由ECMA-262標(biāo)準(zhǔn)第三版定義歪脏,該內(nèi)部屬性包含了函數(shù)被創(chuàng)建的作用域中對象的集合疑俭,這個集合被稱為函數(shù)的作用域鏈,它決定了哪些數(shù)據(jù)能被函數(shù)訪問婿失。
在函數(shù)運(yùn)行過程中標(biāo)識符的解析是沿著作用域鏈一級一級搜索的過程钞艇,從第一個對象開始,逐級向后回溯豪硅,直到找到同名標(biāo)識符為止哩照,找到后不再繼續(xù)遍歷,找不到就報錯懒浮。
閉包:廣義上的閉包就是指一個變量在他自身作用域外被使用了飘弧,就叫發(fā)生了閉包。(父級函數(shù)的局部變量對子級可見嵌溢,可以被子級調(diào)用)
經(jīng)典問題眯牧,一目了然:
for(var i=0;i<elements.length;i++){
elements[i].onclick=function(){
alert(i);
}
}
閉包不能濫用:
閉包會使子函數(shù)保持其作用域鏈的所有變量及函數(shù)與內(nèi)存中,內(nèi)存消耗很大赖草,在使用的時候盡量銷毀父函數(shù)不再使用的變量。