前面一段時間,看到(function(){}),(function(){}())這些函數就犯暈,不知道它到底是什么意思,為什么函數外要加小括號,函數后要加小括號,加和不加到底有什么區別……一直犯迷糊,看了湯姆大叔的《深入理解JavaScript系列(4):立即調用的函數表達式》后才明白它們到底是什么東西,終於將困擾我已久的東西給干掉了。
在這里,我先介紹一下函數引用和函數調用的差別、函數聲明表現形式和函數表達式的表現形式。
一、函數引用和函數調用的差別
函數引用和調用的差別與函數名稱后是否有小括號()有關,函數引用只會單獨出現,但函數調用后面必定會帶有一個小括號,很多時候還附有自變量。
表示方式(舉例說明):
function foo(){ //函數體 } var f = foo; //函數引用 var ff = foo(); //函數調用,可直接調用foo(),也可調用f()
二、函數聲明的表現形式
帶有函數名的函數是函數聲明,包括保留字function,函數名(必有),圓括號中的參數(可有可無)和花括號中的函數主體。
表示方式(舉例說明):
function foo(str){ //函數體 }
三、函數表達式的表現形式
賦值函數,函數外帶有小括號的函數是函數表達式(就舉兩個例子),包括賦值變量(可有),函數外小括號(可有),保留字function,函數名(可有可無),圓括號中的參數(可有可無)和花括號中的函數主體。
表示方式(舉例說明):
//賦值型函數表達式 var f = function foo(str){ //函數體 } //分組括號型函數表達式,這是立即執行函數表達式,后面會講解 (function(){ //函數體 })();
四、函數實例
第一種:
var foo = function(){}
分析:該函數為函數表達式,也可以理解成是一個引用,用foo()調用可執行。
第二種:
var foo = function(){}();
分析:該函數為立即調用函數,這和第一種的區別就是后面有無小括號,也就是函數調用和函數引用的區別,函數調用可理解為自執行函數(最好在function(){}外加一個括號變成(function(){})(),更規范一點);
第三種:
function(){}
分析:該函數缺少名稱,未賦值,所以報錯。
第四種:
function(){}()
分析:function(){}是語句,不是函數表達式,只有表達式才能調用,所以報錯。
第五種:
(function(){})();
分析:(function(){})是函數表達式,能調用,稱為匿名自執行函數。
第六種:
(function(){}());
分析:(function(){}())是函數表達式,可用,稱為匿名自執行函數(湯姆大叔推薦的寫法,我更喜歡第五種寫法)。
第七種:
function foo(){}
分析:該函數為實名函數,可調用。
第八種:
function foo(){}();
分析:解釋和第四種一樣,因為function foo(){}是語句,不是表達式,不能調用,所以報錯。
第九種:
function foo(){}(a);
分析:解釋和第四種一樣,因為function foo(){}是語句,不是表達式,不能調用,但是因為后面括號中傳入了參數,所以未拋出異常,也就為報錯,但是本身還是不執行的。
第十種:
(function foo(){});
分析:function外添加一個括號,所以外部作用域就不能調用foo()這個函數了,里面被當做匿名函數了,我個人認為這樣的函數沒什么意義,既不能調用也不能自執行。
第十一種:
(function foo(){})();
分析:有了十,這個就可以理解為是匿名自執行函數了。但是在ie8以下能執行,該表達式被當做函數聲明,函數聲明有種“置頂解析”的行為,就是不管函數在哪個地方定義,它都會在該作用域頂部默認聲明好。
第十二種:
!function(){}();
分析:其實小括號和js的&&,異或,感嘆號等操作是在函數聲明和表達式消除歧義的,為可執行的。
第十三種:
new function(){}();
分析:可執行。
最后,非常感謝。有哪里講解的不好或者是不正確的地方,希望大家能第一時間反饋給我,希望和大家共同進步~