javascript中聲明函數常用的方法有兩種:函數聲明式和函數表達式.
一、定義
下面分別用兩種方法定義函數:
//函數聲明式 function greeting(){ console.log("hello world"); } //函數表達式 var greeting = function(){ console.log("hello world"); }
二、區別:
1).以函數聲明的方法定義的函數,函數名是必須的,而函數表達式的函數名是可選的。
如果函數表達式聲明的函數有函數名,那么這個函數名就相當於這個函數的一個局部變量,只能在函數內部調用,舉個栗子:
var f = function fact(x) { if (x <= 1) return 1; else return x*fact(x-1); }; alert(fact()); // Uncaught ReferenceError: fact is not defined
2).以函數聲明的方法定義的函數,函數可以在函數聲明之前調用,而函數表達式的函數只能在聲明之后調用(函數聲明整體會被提升到當前作用域的頂部,函數表達式也提升到頂部但是只有其變量名提升,變量提升詳解:https://www.cnblogs.com/vickylinj/p/12190847.html) :
函數表達式與其他表達式一樣,在使用前必須先賦值。以下代碼會導致錯誤。
sayHi(); //錯誤:函數還不存在 var sayHi = function(){ alert("Hi!"); };
3).以函數聲明的方法定義的函數並不是真正的聲明,它們僅僅可以出現在全局中,或者嵌套在其他的函數中,但是它們不能出現在循環,條件或者try/catch/finally中,而函數表達式可以在任何地方聲明。換句話說,函數聲明不是一個完整的語句,所以不能出現在if-else,for循環,finally,try catch語句以及with語句中。
為什么if else 語句里不能用函數聲明定義函數,而可以用函數表達式定義函數:
//不要這樣做! if(condition){ function sayHi(){ alert("Hi!"); } } else { function sayHi(){ alert("Yo!"); } }
表面上看,以上代碼表示在 condition 為 true 時,使用一個 sayHi()的定義;否則,就使用另一個定義。實際上,這在 ECMAScript 中屬於無效語法, JavaScript 引擎會嘗試修正錯誤,將其轉換為合理的狀態。但問題是瀏覽器嘗試修正錯誤的做法並不一致。大多數瀏覽器會返回第二個聲明,忽略condition; Firefox 會在 condition 為 true 時返回第一個聲明。因此這種使用方式很危險,不應該
出現在你的代碼中。不過,如果是使用函數表達式,那就沒有什么問題了。
為什么屬於無效的語法呢?這要從詞法作用來說,在《JavaScript語言精髓與編程實踐》第3章3.2基本語法的結構化含義 ,其中3.2.2.2語法作用域的相關性這一小節回答了以上的疑問,以下屬於摘抄部分:
上面的代碼function的語法作用比表達式的語法作用域高,所以上面if。。。else。。。語句不能包含函數的詞法作用域,JavaScript會將其理解為“平行”的關系,即如下所示:
本例中的代碼也會理解為:
if(condition){} else {} function sayHi(){ alert("Hi!"); } function sayHi(){ alert("Yo!"); )
相當於第二個sayHi()函數覆蓋了第一個,所以會大多數瀏覽器會返回第二個聲明,忽略condition。
當然書中也建議如下作:
//可以這樣做 var sayHi; if(condition){ sayHi = function(){ alert("Hi!"); }; } else { sayHi = function(){ alert("Yo!"); }; }
這個例子不會有什么意外,不同的函數會根據 condition 被賦值給 sayHi。
參照1:https://www.cnblogs.com/menghome/p/9277855.html
參照2:https://blog.csdn.net/qq_41846861/article/details/92692268