函數對於我們這些程序員來說,在熟悉不過啦,我們幾乎每天能在寫函數,使用函數。可是,在javascript中,大家知道幾種函數調用的語句呢?在工作中,常用到的函數調用的語句就一兩 個。那為啥大家知道我還在這裡寫博客,沒事消磨大家的時間。想要知道,請耐心看完,你就明白啦。
javascript中的函數本身是一個變量/值,因此函數調用其實是一個表達式,如圖1
所以,下面代碼就是函數調用語句,它也是一個表達式語句:
functionName();
在javascript中具名函數可以使用上面方法直接調用,匿名函數可以通過引用變量調用,如果沒有引用的匿名函數怎麼調用呢?下面的例子說明這三種情況:
// 實例1:具名函數直接調用function fnName() { // 函數體}
fnName();// 實例2:匿名函數通過引用變量調用var fnName = function () { // 函數體};
fnName();// 實例3:沒有引用的匿名函數的調用(1)(function () { // 函數體}());// 實例4:沒有引用的匿名函數的調用(2)(function () { // 函數體})();// 實例5:沒有引用的匿名函數的調用(3)void function () { // 函數體}();
實例1,2的用法比較常見,實例4在現在很多的框架中使用的也比較多,實例3,5見的就比較少,但是各有其用。
實例3,4都用於“調用函數並返回值”,這兩種表達式有是那個括號,但是意義各不同。如圖2,實例3的說明:
實例4的說明:
其實實例3,4基本是一致。但是它們的運算過程還是有不同:實例3是用強制運算符使函數調用運算得以執行,實例4則是用強制運算符運算“函數直接量聲明”這個表達式,並返回一個函數 自身引用,然後通過函數調用運算符“()”,來操作這個函數的引用。
ps:“函數調用運算符()”在實例3中作用於匿名函數本身,而實例4中卻是作用於一個運算的結果值。
最後的實例5,則用於“調用函數並忽略返回值”。運算符void用於使其後的函數表達式執行運算。然而由此帶來的問題:如果不使用void和()這兩個運算符,而直接使用下面的代碼,是否能 使函數表達式執行呢?
// 實例6:直接使用調用函數運算符"()"function () { // 函數體}()// 實例7:使用語句結束符";"來執行語句function () { // 函數體}();
實例6,7看起來是right,但是事實上它們都不可以執行,原因是它們無法通過腳本引擎的語法檢測。在語法檢測階段,腳本引擎會認為下面的代碼:
function () { // 函數體}// 或function fnName () { // 函數體}
結果是函數聲明,因此實例6,7中使用具名函數也是通不過語法檢測的,正因為這裡是函數聲明,所有實例6,7的代碼位於函數後面的“()”沒有語法意義,它們的代碼被解析成了
// 實例6:語法解釋function () { // 函數體};
();// 實例7:同上
既然“function () {}”被當作完整的語法結構(函數聲明語句)來解釋,那麼也就相當於已經存在語句結束符。因此“();”被當作一個語句表達式解釋,而這樣是錯誤的語法。所以,我們 能看到語法錯誤。
如此,這個語法錯誤是針對“();”,不是針對前面的函數聲明的,下面代碼稍作修改:
// 實例6:通過語法解釋function () { // 函數體}(1,2)
這樣就通過語法的解釋, 因為語句被語法解釋成了。
// 實例6:直接使用調用函數運算符"()"function () { // 函數體};
(1,2);
圖4,被解釋成了兩個單值表達式,,也可以是單個單值表達式。但是這重要的是,這代碼被解釋成了一函數直接量聲明和一個表達式語句,因此它不能起到“執行函數並傳入參數”的作用。如果你真的想在聲明的時候執行一下該函數,那麼可以參考實例3,4,5,用“()”或void運算符將函數聲明變成“單值表達式”
void function () { // 函數體}(1,2);
當引擎在解釋這樣的代碼時,由於先識別到運算符void,於是將後面的匿名函數識別為操作數。
上述就javascript中的函數調用語句,說實在的最後那個我也是看到書本上的,但是,我還是一直沒太明白,如果那位高手可以指點其中的原委那就太感謝啦。也希望這個能幫到其他剛學習javascript的同學們。