JavaScript 中需要創建函數的話,有兩種方法:函數聲明、函數表達式,各自寫法如下:
// 方法一:函數聲明
function foo() {}
// 方法二:函數表達式
var foo = function () {};
另外還有一種自執行函數表達式,主要用於創建一個新的作用域,在此作用域內聲明的變量
不會和其它作用域內的變量沖突或混淆,大多是以匿名函數方式存在,且立即自動執行:
(function () {
// var x = ...
})();
此種自執行函數表達式歸類於以上兩種方法的第二種,也算是函數表達式。
方法一和方法二都創建了一個函數,且命名為 foo,但是二者還是有區別的。
JavaScript 解釋器中存在一種變量聲明被提升(hoisting)的機制,也就是說變量
(函數)的聲明會被提升到作用域的最前面,即使寫代碼的時候是寫在最後面,也還是
會被提升至最前面。
例如以下代碼段:
alert(foo); // function foo() {}
alert(bar); // undefined
function foo() {}
var bar = function bar_fn() {};
alert(foo); // function foo() {}
alert(bar); // function bar_fn() {}
輸出結果分別是function foo() {}、undefined、function foo() {}和function
bar_fn() {}。
可以看到 foo 的聲明是寫在 alert 之後,仍然可以被正確調用,因為 JavaScript 解釋
器會將其提升到 alert 前面,而以函數表達式創建的函數 bar 則不享受此待遇。
那麼bar 究竟有沒有被提升呢,其實用 var 聲明的變量都會被提升,只不過是被先賦值
為 undefined 罷了,所以第二個 alert 彈出了 undefined。
所以,JavaScript 引擎執行以上代碼的順序可能是這樣的:
創建變量 foo 和 bar,並將它們都賦值為 undefined。
創建函數 foo 的函數體,並將其賦值給變量 foo。
執行前面的兩個 alert。
創建函數 bar_fn,並將其賦值給 bar。
執行後面的兩個 alert。
注:
嚴格地說,再 JavaScript 中創建函數的話,還有另外一種方法,稱為“函數構造法”:
var foo = Function('alert("hi!");');
var foo = new Function('alert("hi!");'); // 等同於上面一行
此方法以一個字符串作為參數形成函數體。但是用這種方法,執行效率方面會打折扣,
且似乎無法傳遞參數,所以少用為妙。