大家好谈喳,我是IT修真院武漢分院第7期的學(xué)員景鑫册烈,一枚正直純潔善良的WEB前端程序員。
1.背景介紹
在詳細(xì)講解自執(zhí)行函數(shù)之前婿禽,我們先來說一下這個(gè)函數(shù)在叫法上的爭(zhēng)議赏僧。實(shí)際上不同的人對(duì)自執(zhí)行函數(shù)的理解不太一樣,第一種理解是扭倾,自執(zhí)行即自動(dòng)執(zhí)行淀零,也就是大家平時(shí)所謂的立即執(zhí)行函數(shù)。
還有一種理解膛壹,即自執(zhí)行函數(shù)是在函數(shù)內(nèi)部執(zhí)行函數(shù)本身驾中,即我們平時(shí)常說的遞歸函數(shù)。不管是哪種理解模聋,我們都沒必要去糾結(jié)叫法上的準(zhǔn)確與否肩民,因?yàn)橄啾扔谧詧?zhí)行函數(shù),立即執(zhí)行函數(shù)和遞歸函數(shù)這兩種叫法是我們更加熟悉的链方,實(shí)際上平時(shí)也很少會(huì)看到自執(zhí)行函數(shù)這種叫法持痰。立即執(zhí)行函數(shù)和遞歸函數(shù)都很重要,因此今天打算對(duì)兩種函數(shù)都做一下介紹祟蚀。
2.知識(shí)剖析
知識(shí)點(diǎn)1:直接在函數(shù)后面加()就可以立即執(zhí)行嗎工窍?在函數(shù)聲明后面加括號(hào)為什么會(huì)報(bào)錯(cuò)?
知識(shí)點(diǎn)2:如何實(shí)現(xiàn)立即執(zhí)行函數(shù)
知識(shí)點(diǎn)3:遞歸函數(shù)的幾種用法
3.常見問題
對(duì)函數(shù)聲明以及函數(shù)表達(dá)式理解不夠深入
不知道立即執(zhí)行函數(shù)的用法
4.解決方案
見demo
5.編碼實(shí)戰(zhàn)
5.1對(duì)于函數(shù)表達(dá)式前酿,在后面加括號(hào)即可以讓函數(shù)立即執(zhí)行患雏;例如下面這個(gè)函數(shù),至于為什么加了括號(hào)就可以立即執(zhí)行薪者,我們可以這么理解纵苛,就是像fn1();這樣寫的話言津,函數(shù) 可以立即執(zhí)行是沒問題的攻人,我們?cè)诮?jīng)常會(huì)用到,那么對(duì)于函數(shù)表達(dá)式來說悬槽,fn1就是對(duì)后面的匿名函數(shù)的一個(gè)引用怀吻,因此在后面的匿名函數(shù)后直接加括號(hào),自然也就可以立即執(zhí)行
5.2但是對(duì)于下面這個(gè)函數(shù)初婆,如果直接加()就會(huì)報(bào)錯(cuò)蓬坡;如果按照上面的思路去理解猿棉,在匿名函數(shù)后面直接加上()應(yīng)該是可以立即執(zhí)行的,但是下面這個(gè)函數(shù)之所以會(huì)報(bào)錯(cuò)屑咳,而且會(huì)報(bào)兩個(gè)錯(cuò)誤萨赁,是因?yàn)閖s引擎在解析js代碼的時(shí)候,遇到以function打頭的函數(shù)會(huì)當(dāng)做函數(shù)聲明兆龙,然后會(huì)檢查語(yǔ)法錯(cuò)誤杖爽,那么第一個(gè)括號(hào)處的語(yǔ)法錯(cuò)誤在于函數(shù)聲明是必須要有函數(shù)名字的,而()前面沒有所以報(bào)錯(cuò)紫皇;第二個(gè)括號(hào)處的語(yǔ)法錯(cuò)誤在于函數(shù)聲明到第二個(gè)花括號(hào)處慰安,就已經(jīng)算是結(jié)尾了,后面的()會(huì)被當(dāng)作分組操作符聪铺,這個(gè)()實(shí)際上已經(jīng)和函數(shù)聲明沒關(guān)系了化焕,但是既然有了分組操作符,那就要有表達(dá)式铃剔,不然會(huì)報(bào)錯(cuò)撒桨;
按照上面的分析番宁,我們?nèi)绻诘谝粋€(gè)()前面加上函數(shù)名稱元莫,在第二個(gè)()里面加入表達(dá)式赖阻,那么久不會(huì)報(bào)錯(cuò)了蝶押,我們來看一下效果
可以看到修改了那兩處的問題以后,報(bào)錯(cuò)消失了火欧,但是這個(gè)時(shí)候函數(shù)并沒有執(zhí)行棋电,原因上面也已經(jīng)提到了,就是一旦被當(dāng)作函數(shù)聲明苇侵,那么到花括號(hào)處就算為止了赶盔,后面的()就只當(dāng)作一個(gè)分組操作符,和函數(shù)沒有任何關(guān)系了
5.3那么想讓這種匿名函數(shù)直接執(zhí)行應(yīng)該怎么辦呢榆浓,其實(shí)很簡(jiǎn)單于未,就是在function前面加上一些操作符,這樣js引擎在解析的時(shí)候就不會(huì)把它當(dāng)成是函數(shù)聲明了
5.4以下為最簡(jiǎn)單的遞歸函數(shù),即在函數(shù)內(nèi)部調(diào)用函數(shù)本身萍鲸。
這種函數(shù)有個(gè)問題闷叉,就是當(dāng)函數(shù)被其他變量引用,而原函數(shù)名又被設(shè)置為空對(duì)象后脊阴,遞歸函數(shù)就會(huì)報(bào)錯(cuò)
5.5利用argumens.callee來解決這個(gè)問題,argumens.callee指向當(dāng)前的函數(shù)品擎;
但是這個(gè)方法在嚴(yán)格模式下是不可使用的,因此還不夠完美
5.6利用函數(shù)表達(dá)式構(gòu)造遞歸函數(shù)
6.拓展思考
立即執(zhí)行函數(shù)有哪些用處饥悴?
立即執(zhí)行函數(shù)有很多用處,下面舉一個(gè)例子:
在下面這個(gè)函數(shù)中盲再,result是一個(gè)函數(shù)數(shù)組西设,希望達(dá)到的效果應(yīng)該執(zhí)行數(shù)組中的任何一個(gè)函數(shù),得到的值都應(yīng)該和該函數(shù)在數(shù)組中的索引值是一樣的答朋,但是實(shí)際情況是所有函數(shù)執(zhí)行后得到的值都是10贷揽。之所以會(huì)這樣是因?yàn)閞esult數(shù)組取值的時(shí)候,是通過內(nèi)部函數(shù)去返回外部變量i的值來取得的梦碗,由于內(nèi)部函數(shù)會(huì)創(chuàng)造一個(gè)自己的作用域鏈禽绪,作用域鏈中存放的是i這個(gè)外部變量對(duì)象,這個(gè)變量對(duì)象對(duì)內(nèi)部函數(shù)來說只有一個(gè)洪规,for循環(huán)執(zhí)行完成后的最后的值印屁,即10;
這個(gè)問題可以通過在給result數(shù)組取值外面加立即執(zhí)行函數(shù)來解決斩例,立即執(zhí)行函數(shù)外面的()里面是可以傳參的雄人,下面這個(gè)用法中就是把外部變量i的值通過傳參傳給了num,然后把num的值又傳給了result念赶,這樣最后函數(shù)數(shù)組result中每一個(gè)函數(shù)都是返回當(dāng)時(shí)具體的值础钠,即i當(dāng)時(shí)的值,而不是i最后的值叉谜。
7.參考文獻(xiàn)
參考一:湯姆大叔的博客之立即調(diào)用的函數(shù)表達(dá)式?
參考二:Javascript高級(jí)程序設(shè)計(jì)
8.更多討論
函數(shù)這一部分旗吁,從執(zhí)行環(huán)境、作用域鏈停局、函數(shù)聲明函數(shù)表達(dá)式很钓,到閉包、構(gòu)造函數(shù)和原型鏈都是連在一塊的董栽,類似的函數(shù)問題大家都可以一起討論一下
課后問題:
閉包和匿名函數(shù)的區(qū)別码倦?
答:匿名函數(shù)上面已經(jīng)見過了,類似于常用函數(shù)表達(dá)式中裆泳,function后面直接接一個(gè)()叹洲,沒有函數(shù)名字,即為匿名函數(shù)工禾;閉包是在某個(gè)函數(shù)內(nèi)部的函數(shù)运提,由于閉包的作用域鏈包含有外部函數(shù)的變量對(duì)象蝗柔,因此它可以訪問外部函數(shù)變量,這個(gè)叫閉包
視頻鏈接:
PPT鏈接:PPT?