函數(shù)聲明、函數(shù)表達式、匿名函數(shù)
函數(shù)聲明:使用function關(guān)鍵字聲明一個函數(shù),再指定一個函數(shù)名,叫函數(shù)聲明。
函數(shù)表達式:使用function關(guān)鍵字聲明一個函數(shù),但未給函數(shù)命名,最后將匿名函數(shù)賦予一個變量,叫函數(shù)表達式。
匿名函數(shù): 使用function關(guān)鍵字聲明一個函數(shù),但未給函數(shù)命名,所以叫匿名函數(shù),匿名函數(shù)屬于函數(shù)表達式,匿名函數(shù)有很多作用,賦予一個變量則創(chuàng)建函數(shù),賦予一個事件則成為事件處理程序或創(chuàng)建閉包等等。
function fn(){…} // 函數(shù)聲明
var fn = function(){…} // 函數(shù)表達式
function(){…} // 匿名函數(shù)
函數(shù)聲明和函數(shù)表達式不同之處在于
一、Javascript引擎在解析javascript代碼時會‘函數(shù)聲明提升'(Function declaration Hoisting)當前執(zhí)行環(huán)境(作用域)上的函數(shù)聲明,而函數(shù)表達式必須等到Javascirtp引擎執(zhí)行到它所在行時,才會從上而下一行一行地解析函數(shù)表達式
二、函數(shù)表達式后面可以加括號立即調(diào)用該函數(shù),函數(shù)聲明不可以,只能以fn()形式調(diào)用 。
fn();
function fn(){...}
//正常,因為提升了函數(shù)聲明,函數(shù)調(diào)用可在函數(shù)聲明之前
fn();
var fn=function(){
...
}
//報錯,變量fn還未保存對函數(shù)的引用,函數(shù)調(diào)用必須在函數(shù)表達式之后
var fn=function(){
console.log('Hello World');
}();
//函數(shù)表達式后面加括號,當javascript引擎解析到此處時能立即調(diào)用函數(shù)
function fn(){
console.log('Hello World');
}();
//Chrome 報錯
function(){
console.log('Hello World');
}();
//語法錯誤,雖然匿名函數(shù)屬于函數(shù)表達式,但是未進行賦值操作,
//所以javascript引擎將開頭的function關(guān)鍵字當做函數(shù)聲明,報錯:要求需要一個函數(shù)名
立即執(zhí)行函數(shù)
立即執(zhí)行函數(shù),顧名思義,聲明一個匿名函數(shù),立即執(zhí)行它。
立即執(zhí)行函數(shù)有下面幾種寫法
(function(){ /* code */ })();
(function(){ /* code */ }());
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();
new function(){ /* code */ }
new function(){ /* code */ }() // 只有傳遞參數(shù)時,才需要最后那個圓括號
立即執(zhí)行函數(shù)用法
立即執(zhí)行函數(shù)有什么用呢?
一是不必為函數(shù)命名,避免了污染全局變量。
二是立即執(zhí)行函數(shù)內(nèi)部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變量。
// 寫法一
var a = 1
console.log(a)
// 寫法二
!function(){
var a = 1
console.log(a)
}()
上面代碼中,寫法二比寫法一更好,因為完全避免了污染全局變量。