什么是自執(zhí)行函數(shù)?

大家好,我是IT修真院武漢分院第7期的學員景鑫,一枚正直純潔善良的WEB前端程序員。

1.背景介紹

在詳細講解自執(zhí)行函數(shù)之前,我們先來說一下這個函數(shù)在叫法上的爭議。實際上不同的人對自執(zhí)行函數(shù)的理解不太一樣,第一種理解是,自執(zhí)行即自動執(zhí)行,也就是大家平時所謂的立即執(zhí)行函數(shù)。

還有一種理解,即自執(zhí)行函數(shù)是在函數(shù)內(nèi)部執(zhí)行函數(shù)本身,即我們平時常說的遞歸函數(shù)。不管是哪種理解,我們都沒必要去糾結(jié)叫法上的準確與否,因為相比于自執(zhí)行函數(shù),立即執(zhí)行函數(shù)和遞歸函數(shù)這兩種叫法是我們更加熟悉的,實際上平時也很少會看到自執(zhí)行函數(shù)這種叫法。立即執(zhí)行函數(shù)和遞歸函數(shù)都很重要,因此今天打算對兩種函數(shù)都做一下介紹。

2.知識剖析

知識點1:直接在函數(shù)后面加()就可以立即執(zhí)行嗎?在函數(shù)聲明后面加括號為什么會報錯?

知識點2:如何實現(xiàn)立即執(zhí)行函數(shù)

知識點3:遞歸函數(shù)的幾種用法

3.常見問題

對函數(shù)聲明以及函數(shù)表達式理解不夠深入

不知道立即執(zhí)行函數(shù)的用法

4.解決方案

見demo

5.編碼實戰(zhàn)

5.1對于函數(shù)表達式,在后面加括號即可以讓函數(shù)立即執(zhí)行;例如下面這個函數(shù),至于為什么加了括號就可以立即執(zhí)行,我們可以這么理解,就是像fn1();這樣寫的話,函數(shù) 可以立即執(zhí)行是沒問題的,我們在經(jīng)常會用到,那么對于函數(shù)表達式來說,fn1就是對后面的匿名函數(shù)的一個引用,因此在后面的匿名函數(shù)后直接加括號,自然也就可以立即執(zhí)行

函數(shù)表達式立即執(zhí)行

5.2但是對于下面這個函數(shù),如果直接加()就會報錯;如果按照上面的思路去理解,在匿名函數(shù)后面直接加上()應(yīng)該是可以立即執(zhí)行的,但是下面這個函數(shù)之所以會報錯,而且會報兩個錯誤,是因為js引擎在解析js代碼的時候,遇到以function打頭的函數(shù)會當做函數(shù)聲明,然后會檢查語法錯誤,那么第一個括號處的語法錯誤在于函數(shù)聲明是必須要有函數(shù)名字的,而()前面沒有所以報錯;第二個括號處的語法錯誤在于函數(shù)聲明到第二個花括號處,就已經(jīng)算是結(jié)尾了,后面的()會被當作分組操作符,這個()實際上已經(jīng)和函數(shù)聲明沒關(guān)系了,但是既然有了分組操作符,那就要有表達式,不然會報錯;


函數(shù)聲明想要立即執(zhí)行,會報錯

按照上面的分析,我們?nèi)绻诘谝粋€()前面加上函數(shù)名稱,在第二個()里面加入表達式,那么久不會報錯了,我們來看一下效果


改掉語法錯誤以后的函數(shù)聲明

可以看到修改了那兩處的問題以后,報錯消失了,但是這個時候函數(shù)并沒有執(zhí)行,原因上面也已經(jīng)提到了,就是一旦被當作函數(shù)聲明,那么到花括號處就算為止了,后面的()就只當作一個分組操作符,和函數(shù)沒有任何關(guān)系了

5.3那么想讓這種匿名函數(shù)直接執(zhí)行應(yīng)該怎么辦呢,其實很簡單,就是在function前面加上一些操作符,這樣js引擎在解析的時候就不會把它當成是函數(shù)聲明了


推薦使用的方法,看起來比較具有結(jié)構(gòu)性


也是一種常用的寫法


兩種寫法也可以讓函數(shù)立即執(zhí)行,不過不常用

5.4以下為最簡單的遞歸函數(shù),即在函數(shù)內(nèi)部調(diào)用函數(shù)本身。


最簡單的遞歸函數(shù)

這種函數(shù)有個問題,就是當函數(shù)被其他變量引用,而原函數(shù)名又被設(shè)置為空對象后,遞歸函數(shù)就會報錯


此時fun為空,但gun函數(shù)內(nèi)部還會調(diào)用fun,這樣就會導致報錯

5.5利用argumens.callee來解決這個問題,argumens.callee指向當前的函數(shù);


此時無論fun是否為空對象,內(nèi)部調(diào)用的始終是當前的函數(shù)本身

但是這個方法在嚴格模式下是不可使用的,因此還不夠完美

5.6利用函數(shù)表達式構(gòu)造遞歸函數(shù)


f函數(shù)不會隨著fun的改變而改變,而且在嚴格模式下可用

6.拓展思考

立即執(zhí)行函數(shù)有哪些用處?

立即執(zhí)行函數(shù)有很多用處,下面舉一個例子:

在下面這個函數(shù)中,result是一個函數(shù)數(shù)組,希望達到的效果應(yīng)該執(zhí)行數(shù)組中的任何一個函數(shù),得到的值都應(yīng)該和該函數(shù)在數(shù)組中的索引值是一樣的,但是實際情況是所有函數(shù)執(zhí)行后得到的值都是10。之所以會這樣是因為result數(shù)組取值的時候,是通過內(nèi)部函數(shù)去返回外部變量i的值來取得的,由于內(nèi)部函數(shù)會創(chuàng)造一個自己的作用域鏈,作用域鏈中存放的是i這個外部變量對象,這個變量對象對內(nèi)部函數(shù)來說只有一個,for循環(huán)執(zhí)行完成后的最后的值,即10;

閉包產(chǎn)生的問題

這個問題可以通過在給result數(shù)組取值外面加立即執(zhí)行函數(shù)來解決,立即執(zhí)行函數(shù)外面的()里面是可以傳參的,下面這個用法中就是把外部變量i的值通過傳參傳給了num,然后把num的值又傳給了result,這樣最后函數(shù)數(shù)組result中每一個函數(shù)都是返回當時具體的值,即i當時的值,而不是i最后的值。


使用立即執(zhí)行函數(shù)傳參來解決這個問題

7.參考文獻

參考一:湯姆大叔的博客之立即調(diào)用的函數(shù)表達式?

參考二:Javascript高級程序設(shè)計

8.更多討論

函數(shù)這一部分,從執(zhí)行環(huán)境、作用域鏈、函數(shù)聲明函數(shù)表達式,到閉包、構(gòu)造函數(shù)和原型鏈都是連在一塊的,類似的函數(shù)問題大家都可以一起討論一下

課后問題:

閉包和匿名函數(shù)的區(qū)別?

答:匿名函數(shù)上面已經(jīng)見過了,類似于常用函數(shù)表達式中,function后面直接接一個(),沒有函數(shù)名字,即為匿名函數(shù);閉包是在某個函數(shù)內(nèi)部的函數(shù),由于閉包的作用域鏈包含有外部函數(shù)的變量對象,因此它可以訪問外部函數(shù)變量,這個叫閉包

視頻鏈接:


【武漢-第182期】什么是自執(zhí)行函數(shù)?_騰訊視頻

PPT鏈接:PPT?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容