1 (function(){...})() 3 (function(){...}())
這是兩種js立即執行函數的常見寫法。
基本概念:
函數聲明:function fname(){...}; 使用function關鍵字聲明一個函數,再指定一個函數名。
函數表達式:var fname=function(){...}; 使用function關鍵字聲明一個函數,但未給函數命名,最后將匿名函數賦予給一個變量。
匿名函數:function(){}; 使用function關鍵字聲明一個函數,但未給函數命名。(匿名函數也屬於函數表達式。)
(匿名函數作用很多,賦予一個變量則創建函數,賦予一個事件則成為事件處理程序等。。)
關於函數聲明和函數表達式的區別:
1:函數聲明的Function declaration Hoisting(換成人話就是函數聲明提升),函數表達式不具備這點,它需要被js代碼解析到當前這行時才可以調用。
2:函數表達式后邊加 ()立即調用該函數,函數聲明不可以,它只能以fname()調用。
例子:
1 fName(); 2 function fName(){...}//正確,函數聲明提升,所以 fName()可以寫在函數聲明之前。 3 4 fName(); 5 var fName=function(){...}//錯誤,函數表達式不具備函數聲明提升。 6 7 var fName=function(){...}();//正確,函數表達式后邊加()立即調用函數。 8 9 function fName(){...}();//錯誤,函數聲明必須用fName()調用。
//這行代碼被解析為兩部分: 1函數聲明 function fName(){...}, 2分組表達式(),這表達式有誤,因為括號內沒有表達式,
function (){...}();//匿名函數不可以這么調用,因為function(){...}被當做了聲明,聲明不可以直接()調用。
順便說下立即調用IIFE(Immediately Invoked Function Expression):
(function(){...})() 和 (function(){...}()) 是沒區別的!
傳統的定義函數為:
1 function foo(){...} //這是定義,Declaration,只是讓解釋器知道其存在,不會運行 2 3 foo(); //這是語句,解釋器遇到語句會運行它
為什么要IIFE呢? 1:傳統的方法啰嗦。 2:傳統的方法污染全局命名空間
於是 我們這么寫 function foo(){...}(); 這樣寫行么。。不行,為啥,因為function foo(){...}這部分只是聲明,對解釋器來說,像是你寫了串字符串“function foo(){...}”,它需要的是解析函數,可以用比如eval()來執行它才可以。所以把()直接放聲明后邊是不行的,錯誤語法!
然而,我們距離成功相當接近,只需要把函數聲明變成函數表達式就可以了。方法非常多,最常見的方法是用一對() 包裹起來。 (function foo(){...})();
這就等價於
1 var foo= function(){...}; 2 foo();
當然 還有很多別的方法可以把聲明變成表達式:
1 !function foo(){...}(); 2 +function foo(){...}(); 3 void function() {...}();
需要全局對象的時候,可以這么傳, 舉例:
1 void function(global){ 2 console.log("a's value is: "+global.aa); //可以獲取全局對象中aa的值 3 }(this)
1 var aa=10; 2 (function(a){ 3 console.log("hello world"+a); 4 })(aa);