進(jìn)擊的 JavaScript(五) 之 立即執(zhí)行函數(shù)與閉包

前面的閉包中,提到與閉包相似的立即執(zhí)行函數(shù)粗截,感覺兩者還是比較容易弄混吧,嚴(yán)格來(lái)說(shuō)(因?yàn)橄透叱虒?duì)閉包的定義不同)捣炬,立即執(zhí)行函數(shù)并不屬于閉包熊昌,它不滿足閉包的三個(gè)條件。


一湿酸、圓括號(hào)運(yùn)算符

圓括號(hào)運(yùn)算符也叫分組運(yùn)算符婿屹,它有兩種用法:如果表達(dá)式放在圓括號(hào)中,作用是求值推溃;如果跟在函數(shù)后面昂利,作用是調(diào)用函數(shù)

把表達(dá)式放在圓括號(hào)之中,將返回表達(dá)式的值

console.log((1+2)); // 3

將函數(shù)放在圓括號(hào)中铁坎,會(huì)返回函數(shù)本身蜂奸。如果圓括號(hào)緊跟在函數(shù)的后面,就表示調(diào)用函數(shù)硬萍,即對(duì)函數(shù)求值

console.log((function testa(){return 666;}));
// function testa(){return 666;}

console.log(function testa(){return 666;}());
// 666

注意:圓括號(hào)運(yùn)算符不能為空扩所,否則會(huì)報(bào)錯(cuò)

();//SyntaxError: Unexpected token )

由于圓括號(hào)的作用是求值,如果將語(yǔ)句放在圓括號(hào)之中襟铭,就會(huì)報(bào)錯(cuò)碌奉,因?yàn)檎Z(yǔ)句沒有返回值

(var a = function(){return 666});
// SyntaxError: Unexpected token var


二短曾、函數(shù)聲明

使用 function 關(guān)鍵字創(chuàng)建一個(gè)函數(shù),并且后面帶有函數(shù)名赐劣,叫函數(shù)聲明嫉拐。

function testa(){}


三、匿名函數(shù)

那么使用 function 關(guān)鍵字創(chuàng)建的函數(shù)不帶函數(shù)名呢魁兼? 那就是匿名函數(shù)了婉徘。

function (){}


四、函數(shù)表達(dá)式

那么把匿名函數(shù)賦值給一個(gè)變量呢咐汞?那就是函數(shù)表達(dá)式了盖呼。

var testa = function (){}

其實(shí)呢,函數(shù)表達(dá)式的根本所在化撕,就是阻止了js引擎把 function創(chuàng)建的函數(shù) 當(dāng)作函數(shù)聲明來(lái)解析几晤。下面再詳說(shuō)。


五植阴、立即執(zhí)行函數(shù)(IIFE)

那么立即執(zhí)行函數(shù)呢蟹瘾?

function定義函數(shù)之后,立即調(diào)用該函數(shù)掠手。這種函數(shù)就叫做立即執(zhí)行函數(shù)憾朴,全稱為立即調(diào)用的函數(shù)表達(dá)式IIFE(Imdiately Invoked Function Expression)

1、在本系列進(jìn)擊的 JavaScript(三)中到過(guò)喷鸽,代碼執(zhí)行時(shí)众雷,會(huì)先對(duì)函數(shù)聲明的函數(shù) 進(jìn)行解析(函數(shù)聲明提升),而函數(shù)表達(dá)式做祝,當(dāng)逐行執(zhí)行到它時(shí)砾省,才會(huì)解析。

2剖淀、正因?yàn)楹瘮?shù)聲明的提升纯蛾,導(dǎo)致函數(shù)聲明不能立即執(zhí)行纤房。因?yàn)樽莞簦瘮?shù)聲明時(shí),js只會(huì)解析到大括號(hào)(})就結(jié)束了炮姨,如果后面有()捌刮,只是一個(gè)圓括號(hào)運(yùn)算符。

function testa(){
    console.log("testa")
}("666")

//"666"
//如果后面是一個(gè)空的圓括號(hào)舒岸,會(huì)報(bào)錯(cuò)绅作,上面提到過(guò)鸭津。

所以摔刁,不知道,你有沒有發(fā)現(xiàn)蒙揣,函數(shù)聲明的函數(shù),后面可以不用分號(hào)(;)分隔眯杏,也可以正常執(zhí)行夜焦,而函數(shù)表達(dá)式的后面就必須加分號(hào),不然會(huì)報(bào)錯(cuò)岂贩。你可以自己寫個(gè)小栗子驗(yàn)證下茫经。

3、匿名函數(shù)是不能單獨(dú)寫的萎津,所以就提不上立即執(zhí)行了卸伞。

function (){}
//Uncaught SyntaxError: Unexpected token (

單獨(dú)寫匿名函數(shù),是會(huì)報(bào)錯(cuò)的锉屈,js引擎 會(huì)把它當(dāng)作函數(shù)聲明來(lái)解析荤傲,而函數(shù)聲明就必須要有個(gè)函數(shù)名,所以會(huì)報(bào)錯(cuò)颈渊。
所以弃酌,你通常看到使用匿名函數(shù)儡炼,都是當(dāng)作參數(shù)傳遞的妓湘,或者把匿名函數(shù)轉(zhuǎn)為函數(shù)表達(dá)式。

4乌询、因此榜贴,只有函數(shù)表達(dá)式可以立即執(zhí)行

var testa = function (){
    console.log("testa")
}()
//"testa"

上面提到過(guò),函數(shù)表達(dá)式妹田,就是阻止了js引擎把 |用function創(chuàng)建的函數(shù)| 當(dāng)作函數(shù)聲明來(lái)解析唬党。

注:javascript引擎規(guī)定,如果function關(guān)鍵字出現(xiàn)在行首鬼佣,一律解釋成函數(shù)聲明語(yǔ)句驶拱。

所以,解決方法就是不要讓function出現(xiàn)在行首晶衷,讓引擎將其理解成一個(gè)表達(dá)式蓝纲。

//常用的兩種,使用圓括號(hào)運(yùn)算符
(function(){console.log("666")})()
(function(){console.log("666")}())

//一元運(yùn)算符寫法
!function(){console.log("666")}()
+function(){console.log("666")}()
-function(){console.log("666")}()
~function(){console.log("666")}()

都是都可以把函數(shù)聲明 轉(zhuǎn)為 函數(shù)表達(dá)式,也就是阻止了把其當(dāng)作函數(shù)聲明解析晌纫。


六税迷、立即執(zhí)行函數(shù)在閉包中的應(yīng)用

1、立即執(zhí)行函數(shù)能配合閉包保存狀態(tài)锹漱。

來(lái)看下 上節(jié)內(nèi)容中閉包的例子:

function makeClosures(i){    
    var i = i;  
    return function(){
        console.log(i);     
    }
}

for (var i=1; i<=5; i++) {
    setTimeout(makeClosures(i),i*1000);  
}
//1
//2
//3
//4
//5

現(xiàn)在箭养,我們來(lái)利用立即執(zhí)行函數(shù)來(lái)簡(jiǎn)化它:

for (var i=1; i<=5; i++) {
    setTimeout((function(i){
        return function(){
            console.log(i);
        }
    })(i),i*1000);
}

第一個(gè)匿名函數(shù)執(zhí)行完畢后,返回了第二個(gè)匿名函數(shù)哥牍。第二個(gè)匿名函數(shù)被當(dāng)做setTimeout 的第一個(gè)參數(shù)傳入進(jìn)去毕泌。因?yàn)?setTimeout函數(shù)執(zhí)行了5次喝检,所以立即執(zhí)行函數(shù)里每次都會(huì)返回了一個(gè)沒有被執(zhí)行的匿名函數(shù),(這里就是返回了5個(gè)匿名函數(shù))撼泛,每個(gè)匿名函數(shù)內(nèi)部保存著每次傳進(jìn)來(lái)的i值蛇耀,因此,每個(gè)i 都是不一樣的坎弯,所以纺涤,就得到了想要的結(jié)果

2、立即執(zhí)行函數(shù)配合閉包 模塊化中應(yīng)用

(function(){
    var meg = "hello zdx";
    
    function say(arg){
        arg = arg || meg;
        console.log(arg)
    }
    
    window.say = say;
})(window)

window.say();

//"hello zdx"

首先立即執(zhí)行函數(shù)抠忘,它是個(gè)匿名函數(shù)撩炊,你是得不到它的函數(shù)引用,這樣崎脉,就避免了全局變量污染拧咳。其次,由于函數(shù)作用域的規(guī)則囚灼,在匿名函數(shù)外部是訪問(wèn)不了函數(shù)內(nèi)的變量骆膝,函數(shù)等的。所以灶体,也經(jīng)常用立即執(zhí)行函數(shù)模擬塊級(jí)作用域阅签。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蝎抽,隨后出現(xiàn)的幾起案子政钟,更是在濱河造成了極大的恐慌,老刑警劉巖樟结,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件养交,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瓢宦,警方通過(guò)查閱死者的電腦和手機(jī)碎连,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)驮履,“玉大人鱼辙,你說(shuō)我怎么就攤上這事∑N” “怎么了座每?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)摘悴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)舰绘,這世上最難降的妖魔是什么蹂喻? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任葱椭,我火速辦了婚禮,結(jié)果婚禮上口四,老公的妹妹穿的比我還像新娘孵运。我一直安慰自己,他們只是感情好蔓彩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布治笨。 她就那樣靜靜地躺著,像睡著了一般赤嚼。 火紅的嫁衣襯著肌膚如雪旷赖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天更卒,我揣著相機(jī)與錄音等孵,去河邊找鬼。 笑死蹂空,一個(gè)胖子當(dāng)著我的面吹牛俯萌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播上枕,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼咐熙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辨萍?” 一聲冷哼從身側(cè)響起糖声,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎分瘦,沒想到半個(gè)月后蘸泻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嘲玫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年悦施,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片去团。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抡诞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出土陪,到底是詐尸還是另有隱情昼汗,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布鬼雀,位于F島的核電站顷窒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鞋吉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一鸦做、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谓着,春花似錦泼诱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至舷蒲,卻和暖如春耸袜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阿纤。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工句灌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欠拾。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓胰锌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親藐窄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子资昧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容