原文鏈接:[譯] JavaScript:立即執(zhí)行函數(shù)表達(dá)式(IIFE)
(一) JavaScript 中的圓括號(hào)
JavaScript 中的圓括號(hào)不能包含聲明搏存,當(dāng)我們將函數(shù)聲明放在一個(gè)圓括號(hào)里面時(shí)防泵,語法分析器會(huì)將其表達(dá)成一個(gè)函數(shù)表達(dá)式。
- 當(dāng)圓括號(hào)出現(xiàn)在匿名函數(shù)的末尾想要調(diào)用函數(shù)時(shí)院领,它會(huì)默認(rèn)將函數(shù)當(dāng)成是函數(shù)聲明抱怔。
- 當(dāng)圓括號(hào)包裹函數(shù)時(shí)窿春,它會(huì)默認(rèn)將函數(shù)作為表達(dá)式去解析,而不是函數(shù)聲明政勃。
因此唧龄,實(shí)現(xiàn)一個(gè)立即執(zhí)行函數(shù)的方式很簡(jiǎn)單:
(1) 這里將函數(shù)聲明放在圓括號(hào)里,表示表達(dá)式奸远,后面的圓括號(hào)表示立即執(zhí)行既棺。
(function(){/* code */}());
(2) 如果我們是這樣寫的話讽挟,會(huì)報(bào)錯(cuò),因?yàn)檫@是一個(gè)函數(shù)聲明丸冕。
function(){ /* code */}();
(3) 當(dāng)然耽梅,如果將其改為表達(dá)式的寫法是可以的
var foo = function(){console.log(1)}()
(二) 保存閉包狀態(tài)
閉包: 任何一個(gè)定義在函數(shù)內(nèi)部的函數(shù)都可以使用外面函數(shù)傳遞進(jìn)來的參數(shù)和變量。立即執(zhí)行函數(shù)一個(gè)最顯著的優(yōu)勢(shì)是就算它沒有命名或者說是匿名胖烛,函數(shù)表達(dá)式也可以在沒有使用標(biāo)識(shí)符的情況下被立即調(diào)用眼姐,一個(gè)閉包也可以在沒有當(dāng)前變量污染的情況下被使用。
// 它的運(yùn)行原理可能并不像你想的那樣佩番,因?yàn)閌i`的值從來沒有被鎖定众旗。
// 相反的,每個(gè)鏈接趟畏,當(dāng)被點(diǎn)擊時(shí)(循環(huán)已經(jīng)被很好的執(zhí)行完畢)贡歧,因此會(huì)彈出所有元素的總數(shù),
// 因?yàn)檫@是 `i` 此時(shí)的真實(shí)值拱镐。
var elems = document.getElementsByTagName('a');
for(var i = 0;i < elems.length; i++ ) {
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + i)
},false);
}
// 而像下面這樣改寫艘款,便可以了持际,因?yàn)樵贗IFE里沃琅,`i`值被鎖定在了`lockedInIndex`里。
// 在循環(huán)結(jié)束執(zhí)行時(shí)蜘欲,盡管`i`值的數(shù)值是所有元素的總和益眉,但每一次函數(shù)表達(dá)式被調(diào)用時(shí),
// IIFE 里的 `lockedInIndex` 值都是`i`傳給它的值,所以當(dāng)鏈接被點(diǎn)擊時(shí)姥份,正確的值被彈出郭脂。
var elems = document.getElementsByTagName('a');
for(var i = 0;i < elems.length;i++) {
(function(lockedInIndex){
elems[i].addEventListener('click',function(e){
e.preventDefault();
alert('I am link #' + lockedInIndex);
},false)
})(i);
}
//你同樣可以像下面這樣使用IIFE,僅僅只用括號(hào)包括點(diǎn)擊處理函數(shù)澈歉,并不包含整個(gè)`addEventListener`展鸡。
//無論用哪種方式,這兩個(gè)例子都可以用IIFE將值鎖定埃难,不過我發(fā)現(xiàn)前面一個(gè)例子更可讀
var elems = document.getElementsByTagName( 'a' );
for ( var i = 0; i < elems.length; i++ ) {
elems[ i ].addEventListener( 'click', (function( lockedInIndex ){
return function(e){
e.preventDefault();
alert( 'I am link #' + lockedInIndex );
};
})( i ),false);
}
注:立即執(zhí)行函數(shù)既可以是命名函數(shù)莹弊,也可以是匿名函數(shù)。