函數(shù)對(duì)于我們這些程序員來(lái)說(shuō),在熟悉不過(guò)啦,我們幾乎每天能在寫(xiě)函數(shù),使用函數(shù)。可是,在javascript中,大家知道幾種函數(shù)調(diào)用的語(yǔ)句呢?在工作中,常用到的函數(shù)調(diào)用的語(yǔ)句就一兩 個(gè)。那為啥大家知道我還在這里寫(xiě)博客,沒(méi)事消磨大家的時(shí)間。想要知道,請(qǐng)耐心看完,你就明白啦。
javascript中的函數(shù)本身是一個(gè)變量/值,因此函數(shù)調(diào)用其實(shí)是一個(gè)表達(dá)式,如圖1
所以,下面代碼就是函數(shù)調(diào)用語(yǔ)句,它也是一個(gè)表達(dá)式語(yǔ)句:
functionName();
在javascript中具名函數(shù)可以使用上面方法直接調(diào)用,匿名函數(shù)可以通過(guò)引用變量調(diào)用,如果沒(méi)有引用的匿名函數(shù)怎么調(diào)用呢?下面的例子說(shuō)明這三種情況:
// 實(shí)例1:具名函數(shù)直接調(diào)用function fnName() { // 函數(shù)體} fnName();// 實(shí)例2:匿名函數(shù)通過(guò)引用變量調(diào)用var fnName = function () { // 函數(shù)體}; fnName();// 實(shí)例3:沒(méi)有引用的匿名函數(shù)的調(diào)用(1)(function () { // 函數(shù)體}());// 實(shí)例4:沒(méi)有引用的匿名函數(shù)的調(diào)用(2)(function () { // 函數(shù)體})();// 實(shí)例5:沒(méi)有引用的匿名函數(shù)的調(diào)用(3)void function () { // 函數(shù)體}();
實(shí)例1,2的用法比較常見(jiàn),實(shí)例4在現(xiàn)在很多的框架中使用的也比較多,實(shí)例3,5見(jiàn)的就比較少,但是各有其用。
實(shí)例3,4都用于“調(diào)用函數(shù)并返回值”,這兩種表達(dá)式有是那個(gè)括號(hào),但是意義各不同。如圖2,實(shí)例3的說(shuō)明:
實(shí)例4的說(shuō)明:
其實(shí)實(shí)例3,4基本是一致。但是它們的運(yùn)算過(guò)程還是有不同:實(shí)例3是用強(qiáng)制運(yùn)算符使函數(shù)調(diào)用運(yùn)算得以執(zhí)行,實(shí)例4則是用強(qiáng)制運(yùn)算符運(yùn)算“函數(shù)直接量聲明”這個(gè)表達(dá)式,并返回一個(gè)函數(shù) 自身引用,然后通過(guò)函數(shù)調(diào)用運(yùn)算符“()”,來(lái)操作這個(gè)函數(shù)的引用。
ps:“函數(shù)調(diào)用運(yùn)算符()”在實(shí)例3中作用于匿名函數(shù)本身,而實(shí)例4中卻是作用于一個(gè)運(yùn)算的結(jié)果值。
最后的實(shí)例5,則用于“調(diào)用函數(shù)并忽略返回值”。運(yùn)算符void用于使其后的函數(shù)表達(dá)式執(zhí)行運(yùn)算。然而由此帶來(lái)的問(wèn)題:如果不使用void和()這兩個(gè)運(yùn)算符,而直接使用下面的代碼,是否能 使函數(shù)表達(dá)式執(zhí)行呢?
// 實(shí)例6:直接使用調(diào)用函數(shù)運(yùn)算符"()"function () { // 函數(shù)體}()// 實(shí)例7:使用語(yǔ)句結(jié)束符";"來(lái)執(zhí)行語(yǔ)句function () { // 函數(shù)體}();
實(shí)例6,7看起來(lái)是right,但是事實(shí)上它們都不可以執(zhí)行,原因是它們無(wú)法通過(guò)腳本引擎的語(yǔ)法檢測(cè)。在語(yǔ)法檢測(cè)階段,腳本引擎會(huì)認(rèn)為下面的代碼:
function () { // 函數(shù)體}// 或function fnName () { // 函數(shù)體}
結(jié)果是函數(shù)聲明,因此實(shí)例6,7中使用具名函數(shù)也是通不過(guò)語(yǔ)法檢測(cè)的,正因?yàn)檫@里是函數(shù)聲明,所有實(shí)例6,7的代碼位于函數(shù)后面的“()”沒(méi)有語(yǔ)法意義,它們的代碼被解析成了
// 實(shí)例6:語(yǔ)法解釋function () { // 函數(shù)體}; ();// 實(shí)例7:同上
既然“function () {}”被當(dāng)作完整的語(yǔ)法結(jié)構(gòu)(函數(shù)聲明語(yǔ)句)來(lái)解釋?zhuān)敲匆簿拖喈?dāng)于已經(jīng)存在語(yǔ)句結(jié)束符。因此“();”被當(dāng)作一個(gè)語(yǔ)句表達(dá)式解釋?zhuān)@樣是錯(cuò)誤的語(yǔ)法。所以,我們 能看到語(yǔ)法錯(cuò)誤。
如此,這個(gè)語(yǔ)法錯(cuò)誤是針對(duì)“();”,不是針對(duì)前面的函數(shù)聲明的,下面代碼稍作修改:
// 實(shí)例6:通過(guò)語(yǔ)法解釋function () { // 函數(shù)體}(1,2)
這樣就通過(guò)語(yǔ)法的解釋?zhuān)?因?yàn)檎Z(yǔ)句被語(yǔ)法解釋成了。
// 實(shí)例6:直接使用調(diào)用函數(shù)運(yùn)算符"()"function () { // 函數(shù)體}; (1,2);
圖4,被解釋成了兩個(gè)單值表達(dá)式,,也可以是單個(gè)單值表達(dá)式。但是這重要的是,這代碼被解釋成了一函數(shù)直接量聲明和一個(gè)表達(dá)式語(yǔ)句,因此它不能起到“執(zhí)行函數(shù)并傳入?yún)?shù)”的作用。如果你真的想在聲明的時(shí)候執(zhí)行一下該函數(shù),那么可以參考實(shí)例3,4,5,用“()”或void運(yùn)算符將函數(shù)聲明變成“單值表達(dá)式”
void function () { // 函數(shù)體}(1,2);
當(dāng)引擎在解釋這樣的代碼時(shí),由于先識(shí)別到運(yùn)算符void,于是將后面的匿名函數(shù)識(shí)別為操作數(shù)。
上述就javascript中的函數(shù)調(diào)用語(yǔ)句,說(shuō)實(shí)在的最后那個(gè)我也是看到書(shū)本上的,但是,我還是一直沒(méi)太明白,如果那位高手可以指點(diǎn)其中的原委那就太感謝啦。也希望這個(gè)能幫到其他剛學(xué)習(xí)javascript的同學(xué)們。