對javascript匿名函數(shù)的理解(透徹版)

網(wǎng)上很多解釋,我無法理解捌治,我想知道原理衔彻。。填具。這篇文章應該可以透徹一點

Query片段:

(function(){

//這里忽略jQuery所有實現(xiàn)

})();

半年前初次接觸jQuery的時候统舀,我也像其他人一樣很興奮地想看看源碼是什么樣的。然而劳景,在看到源碼的第一眼誉简,我就迷糊了。為什么只有一個匿

名函數(shù)又沒看到運行(當然是運行了……)盟广,就能有jQuery這么個函數(shù)庫了闷串?于是,我抱著疑問來到CSDN筋量。結(jié)果相信現(xiàn)在很多人都很清楚了(因為在我之

后也不乏來者烹吵,呵呵~)。當一個匿名函數(shù)被括起來桨武,然后再在后面加一個括號肋拔,這個匿名函數(shù)就能立即運行起來!真神奇哦呀酸!

嘿嘿凉蜂!胡

鬧到此為止。在這一節(jié),我們碰到的jQuery片段是一組立即運行的匿名函數(shù)窿吩。而這種用法在論壇上也曾引起過激辯——這段代碼究竟屬不

屬于閉包呢茎杂?帶著這個疑問,我們從基礎開始爆存,分析每個關鍵要素蛉顽,尋找屬于自己的答案蝗砾。(沒錯先较,自己的答案!在我看來悼粮,所有理論只是形式闲勺,只要它有利于我們

的應用實現(xiàn),就是可取的——黑貓白貓扣猫,抓到老鼠的就是好貓2搜)

要說匿名函數(shù),我們首先要由函數(shù)本身說起申尤。函數(shù)的定義如下:

函數(shù)是將唯一的輸出值賦予給每一輸入的“法則”癌幕。

當然,這只是數(shù)學上的定義昧穿。但是勺远,在計算機編程語言中,函數(shù)的定義也八九不離十时鸵。因為胶逢,我們都知道,計算機中的函數(shù)饰潜,也類似數(shù)學定義中的描述初坠,它是將輸入的若干數(shù)據(jù),經(jīng)過代碼設定的邏輯操作處理后彭雾,返回唯一的輸出的一組代碼組合塊碟刺。——當然,特例是薯酝,輸入的數(shù)據(jù)為空或輸出的數(shù)據(jù)為空半沽,或者兩者都為空。

下面蜜托,我們先初步了解一下和匿名函數(shù)相關的概念抄囚。

函數(shù)聲明(function 語句)

要使用一個函數(shù),我們就得首先聲明它的存在橄务。而我們最常用的方式就是使用function語句來定義一個函數(shù)幔托,如:

view plaincopy to clipboardprint?

function?abc(){

//?code?to?process

}

當然,你的函數(shù)也可以是帶參數(shù)的,甚至是帶返回值的重挑。

view plaincopy to clipboardprint?

function?abc(x,y){

return?x+y;

}

但是嗓化,無論你怎么去定義你的函數(shù),JS解釋器都會把它翻譯成一個Function對象谬哀。例如刺覆,你在定義上面的其中一個例子的函數(shù)號,再輸入如下代碼:

view plaincopy to clipboardprint?

alert(typeof?abc);//?"function"

你的瀏覽器就會彈出提示框史煎,提示你abc是一個Function對象谦屑。那么Function對象究竟是什么呢?

Function 對象

Function對象是JavaScript里面的固有對象篇梭,所有的函數(shù)實際上都是一個Function對象氢橙。關于這個方面的討論,我們留到下一個專題節(jié)恬偷。我們先看看悍手,F(xiàn)unction對象能不能直接運用構(gòu)造函數(shù)創(chuàng)建一個新的函數(shù)呢?答案是肯定的袍患。例如:

view plaincopy to clipboardprint?

var?abc?=?new?Function("x","y","return?x*y;");

alert(abc(2,3));//?"6"

相信大家現(xiàn)在對如何聲明一個函數(shù)應該是有所了解了坦康。那么什么才是匿名函數(shù)呢?

聲明匿名函數(shù)

顧名思義诡延,匿名函數(shù)就是沒有實際名字的函數(shù)滞欠。例如,我們把上面的例子中孕暇,函數(shù)的名字去掉仑撞,再判斷一下他是不是一個函數(shù):

view plaincopy to clipboardprint?

alert(typeof?function(){});//?"function"

alert(typeof?function(x,y){return?x+y;});//?"function"

alert(typeof?new?Function("x","y","return?x*y;"))//?"function"

我們可以很容易地看到,它們?nèi)际荈unction對象妖滔,換言之隧哮,他們都是函數(shù),但是他們都有一個特點——沒有名字座舍。所以我們把他們稱作“匿名函數(shù)”沮翔。然而,正因為他們沒有“名字”曲秉,我們也沒有辦法找到他們采蚀。這就引申了如何去調(diào)用一個匿名函數(shù)的問題了。

匿名函數(shù)的調(diào)用

要調(diào)用一個函數(shù)承二,我們必須要有方法定位它榆鼠,引用它。所以亥鸠,我們會需要幫它找一個名字妆够。例如:

view plaincopy to clipboardprint?

var?abc=function(x,y){

return?x+y;

}

alert(abc(2,3));//?"5"

上面的操作其實就等于換個方式去定義函數(shù)识啦,這種用法是我們比較頻繁遇到的。例如我們在設定一個DOM元素事件處理函數(shù)的時候神妹,我們通常都不會為他們定名字颓哮,而是賦予它的對應事件引用一個匿名函數(shù)。

對匿名函數(shù)的調(diào)用其實還有一種做法鸵荠,也就是我們看到的jQuery片段——使用()將匿名函數(shù)括起來冕茅,然后后面再加一對小括號(包含參數(shù)列表)。我們再看一下以下例子:

view plaincopy to clipboardprint?

alert((function(x,y){return?x+y;})(2,3));//?"5"

alert((new?Function("x","y","return?x*y;"))(2,3));//?"6"

很多人或許會奇怪蛹找,為什么這種方法能成功調(diào)用呢姨伤?覺得這個應用奇怪的人就看一下我以下這段解釋吧。

大家知道小括號的作用嗎熄赡?小括號能把我們的表達式組合分塊姜挺,并且每一塊齿税,也就是每一對小括號彼硫,都有一個返回值。這個返回值實際上也就是小括號中表達式的返回值凌箕。所以拧篮,當我們用一對小括號把匿名函數(shù)括起來的時候,實際上小括號對返回的牵舱,就是一個匿名函數(shù)的Function對象串绩。因此,小括號對加上匿名函數(shù)就如同有名字的函數(shù)般被我們?nèi)〉盟囊梦恢昧宋弑凇K匀绻谶@個引用變量后面再加上參數(shù)列表礁凡,就會實現(xiàn)普通函數(shù)的調(diào)用形式。

不知道以上的文字表述大家能不能看明白慧妄,如果還是理解不了的話顷牌,再看一下以下的代碼試試吧。

view plaincopy to clipboardprint?

var?abc=function(x,y){return?x+y;};//?把匿名函數(shù)對象賦給abc

//?abc的constructor就和匿名函數(shù)的constructor一樣了塞淹。也就是說窟蓝,兩個函數(shù)的實現(xiàn)是一樣的。

alert((abc).constructor==(function(x,y){return?x+y;}).constructor);

PS:constructor是指創(chuàng)建對象的函數(shù)饱普。也就是函數(shù)對象所代表的函數(shù)體运挫。

總之,將其(被小括號包含的匿名函數(shù))理解為括號表達式返回的函數(shù)對象套耕,然后就可以對這個函數(shù)對象作正常的參數(shù)列表調(diào)用了谁帕。(前面這里犯了個錯

誤,只有函數(shù)表達式還是不能直接調(diào)用函數(shù)的冯袍,去掉匿名函數(shù)括號必須要伴隨將表達式賦值匈挖。也就是(function(){alert(1)})()應該是與

a=function(){alert(1)}()等價,不能連a=都去掉。)

閉包

閉包是什么关划?閉包是指某種程序語言中的代碼塊允許一級函數(shù)存在并且在一級函數(shù)中所定義的自由變量能不被釋放小染,直到一級函數(shù)被釋放前,一級函數(shù)外也能應用這些未釋放的自由變量贮折。

怎樣裤翩?看得一頭冒汗吧……沒事,我也是(雖然是我是了解的调榄,只是表達能力的問題)踊赠。讓我們換個更加簡單的方法說明:閉包,其實是一種語言特性每庆,它是指的是程序設計語言中筐带,允許將函數(shù)看作對象,然后能像在對象中的操作搬在函數(shù)中定義實例(局部)變量缤灵,而這些變量能在函數(shù)中保存到函數(shù)的實例對象銷毀為止伦籍,其它代碼塊能通過某種方式獲取這些實例(局部)變量的值并進行應用擴展。

不知道這么再解釋后會否更加清晰腮出,如果還是不明白帖鸦,那么我們再簡化一下:閉包,其實就是指程序語言中能讓代碼調(diào)用已運行的函數(shù)中所定義的局部變量胚嘲。

現(xiàn)在我們看一個例子:

view plaincopy to clipboardprint?

var?abc=function(y){

var?x=y;//?這個是局部變量

return?function(){

alert(x++);//?就是這里調(diào)用了閉包特性中的一級函數(shù)局部變量的x作儿,并對它進行操作

alert(y--);//?引用的參數(shù)變量也是自由變量

}}(5);//?初始化

abc();//?"5"?"5"

abc();//?"6"?"4"

abc();//?"7"?"3"

alert(x);//?報錯!“x”未定義馋劈!

看到這里攻锰,你能判斷究竟jQuery的那個代碼片段是否閉包了嗎?

以我的理解來說吧妓雾。是

否應用了閉包特性娶吞,必須確定該段代碼有沒有

最重要的要素:未銷毀的局部變量。那么很顯然君珠,沒有任何實現(xiàn)的匿名函數(shù)不可能應用了閉包特性寝志。但如果匿名函數(shù)里面有實現(xiàn)呢?那也還得確定它的實現(xiàn)中有沒有

用到那些未銷毀的局部變量策添。所以如果問你那個開篇中的jQuery代碼片段是應用了JS里的什么特性材部?那么它只是匿名函數(shù)與匿名函數(shù)的調(diào)用而已。但是唯竹,它

隱含了閉包的特性乐导,并且隨時可以實現(xiàn)閉包應用。因為JS天生就是有這個特性的浸颓!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末物臂,一起剝皮案震驚了整個濱河市旺拉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棵磷,老刑警劉巖蛾狗,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仪媒,居然都是意外死亡沉桌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門算吩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來留凭,“玉大人,你說我怎么就攤上這事偎巢“梗” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵压昼,是天一觀的道長求冷。 經(jīng)常有香客問我,道長巢音,這世上最難降的妖魔是什么遵倦? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮官撼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘似谁。我一直安慰自己傲绣,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布巩踏。 她就那樣靜靜地躺著秃诵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪塞琼。 梳的紋絲不亂的頭發(fā)上菠净,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音彪杉,去河邊找鬼毅往。 笑死,一個胖子當著我的面吹牛派近,可吹牛的內(nèi)容都是我干的攀唯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼渴丸,長吁一口氣:“原來是場噩夢啊……” “哼侯嘀!你這毒婦竟也來了另凌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤戒幔,失蹤者是張志新(化名)和其女友劉穎吠谢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诗茎,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡囊卜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了错沃。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栅组。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枢析,靈堂內(nèi)的尸體忽然破棺而出玉掸,到底是詐尸還是另有隱情,我是刑警寧澤醒叁,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布司浪,位于F島的核電站,受9級特大地震影響把沼,放射性物質(zhì)發(fā)生泄漏啊易。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一饮睬、第九天 我趴在偏房一處隱蔽的房頂上張望租谈。 院中可真熱鬧,春花似錦捆愁、人聲如沸割去。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呻逆。三九已至,卻和暖如春菩帝,著一層夾襖步出監(jiān)牢的瞬間咖城,已是汗流浹背抒钱。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工抹估, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喘沿,地道東北人市俊。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓退个,卻偏偏與公主長得像赠法,于是被迫代替她去往敵國和親勋功。 傳聞我的和親對象是個殘疾皇子递鹉,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

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