前面一段時間,看到(function(){}),(function(){}())這些函數就犯暈,不知道它究竟是什麼意思,爲何函數外要加小括號,函數後要加小括號,加和不加到底有什麼區別……一直犯迷糊,看了湯姆大叔的《深刻理解JavaScript系列(4):當即調用的函數表達式》後才明白它們究竟是什麼東西,終於將困擾我已久的東西給幹掉了。html
在這裏,我先介紹一下函數引用和函數調用的差異、函數聲明表現形式和函數表達式的表現形式。函數
1、函數引用和函數調用的差異htm
函數引用和調用的差異與函數名稱後是否有小括號()有關,函數引用只會單獨出現,但函數調用後面一定會帶有一個小括號,不少時候還附有自變量。blog
表示方式(舉例說明):ip
function foo(){ //函數體 } var f = foo; //函數引用 var ff = foo(); //函數調用,可直接調用foo(),也可調用f()
二、函數聲明的表現形式作用域
帶有函數名的函數是函數聲明,包括保留字function,函數名(必有),圓括號中的參數(無關緊要)和花括號中的函數主體。get
表示方式(舉例說明):it
function foo(str){ //函數體 }
3、函數表達式的表現形式io
賦值函數,函數外帶有小括號的函數是函數表達式(就舉兩個例子),包括賦值變量(可有),函數外小括號(可有),保留字function,函數名(無關緊要),圓括號中的參數(無關緊要)和花括號中的函數主體。function
表示方式(舉例說明):
//賦值型函數表達式 var f = function foo(str){ //函數體 } //分組括號型函數表達式,這是當即執行函數表達式,後面會講解 (function(){ //函數體 })();
4、函數實例
第一種:
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(){}();
分析:可執行。
最後,很是感謝。有哪裏講解的很差或者是不正確的地方,但願你們能第一時間反饋給我,但願和你們共同進步~