1、函數聲明與函數表達式
函數聲明:
function 函數名稱 (參數:可選){ 函數體 }
函數表達式(函數語句):
function 函數名稱(可選)(參數:可選){ 函數體 }
function foo(){} // 聲明,因爲它是程序的一部分
var bar = function foo(){}; // 表達式,因爲它是賦值表達式的一部分
new function bar(){}; // 表達式,因爲它是new表達式
(function(){
function bar(){} // 聲明,因爲它是函數體的一部分
})();
如果不聲明函數名稱,則肯定是函數表達式,但如果聲明瞭函數名稱,如何判斷是函數聲明還是函數表達式?
ECMAScript是通過上下文來區分的,如果function 函數名稱(){}是作爲賦值表達式的一部分的話,那它就是一個函數表達式,如果function 函數名稱(){}被包含在一個函數體內,或者位於程序的最頂部的話,那它就是一個函數聲明。
函數表達式和函數聲明的差別:函數聲明在任何表達式解析和求值之前先被解析和求值。如:
alert(fn());
function fn() {
return 'Hello world!';
}
函數聲明在條件語句內雖然可以用,但是沒有被標準化,也就是說不同的環境可能有不同的執行結果,所以這樣情況下,最好使用函數表達式:
// 千萬別這樣做!
// 因爲有的瀏覽器會返回first的這個function,而有的瀏覽器返回的卻是第二個
if (true) {
function foo() {
return 'first';
}
}
else {
function foo() {
return 'second';
}
}
foo();
// 相反,這樣情況,我們要用函數表達式
var foo;
if (true) {
foo = function() {
return 'first';
};
}
else {
foo = function() {
return 'second';
};
}
foo();
小結:函數聲明只能出現在程序或函數體內。它不能出現在if、for、while等Block內。Block塊內只能含有Statement語句。
同時因爲函數表達式不能以function開頭,故函數表達式同樣不能出現在Statement語句和Block塊內。
2、語句函數
在ECMAScript的語法擴展中,有一個是函數語句,目前只有基於Gecko的瀏覽器實現了該擴展,一般來說不推薦使用
函數語句和函數表達式的區別:
一般語句能用的地方,函數語句也能用,當然也包括Block塊中。
函數語句不是在變量初始化期間聲明的,而是在運行時聲明的——與函數表達式一樣。不過,函數語句的標識符一旦聲明能在函數的整個作用域生效了。(聲明函數——函數,函數表達式——表達式,語句函數——函數)
函數表達式的新名字只能在函數內部作用域內有效,外部作用域無效。
var f = function foo(){
return typeof foo; // foo是在內部作用域內有效
};
// foo在外部用於是不可見的
typeof foo; // "undefined"
f(); // "function"