Javascript的函數聲明和函數表達式
- 2019 年 10 月 5 日
- 筆記
Javascript定義函數有兩種類型
函數聲明
// 函數聲明 function wscat(type){ return type==="wscat"; }
函數表達式
// 函數表達式 var oaoafly = function(type){ return type==="oaoafly"; }
先看下面這個經典問題,在一個程式裡面同時用函數聲明和函數表達式定義一個名為getName的函數
getName()//oaoafly var getName = function() { console.log('wscat') } getName()//wscat function getName() { console.log('oaoafly') } getName()//wscat
上面的程式碼看起來很類似,感覺也沒什麼太大差別。但實際上,Javascript函數上的一個「陷阱」就體現在Javascript兩種類型的函數定義上。
JavaScript 解釋器中存在一種變數聲明被提升的機制,也就是說函數聲明會被提升到作用域的最前面,即使寫程式碼的時候是寫在最後面,也還是會被提升至最前面。
而用函數表達式創建的函數是在運行時進行賦值,且要等到表達式賦值完成後才能調用
var getName//變數被提升,此時為undefined getName()//oaoafly 函數被提升 這裡受函數聲明的影響,雖然函數聲明在最後可以被提升到最前面了 var getName = function() { console.log('wscat') }//函數表達式此時才開始覆蓋函數聲明的定義 getName()//wscat function getName() { console.log('oaoafly') } getName()//wscat 這裡就執行了函數表達式的值
所以可以分解為這兩個簡單的問題來看清楚區別的本質
var getName; console.log(getName)//undefined getName()//Uncaught TypeError: getName is not a function var getName = function() { console.log('wscat') } var getName; console.log(getName)//function getName() {console.log('oaoafly')} getName()//oaoafly function getName() { console.log('oaoafly') }
這個區別看似微不足道,但在某些情況下確實是一個難以察覺並且「致命「的陷阱。出現這個陷阱的本質原因體現在這兩種類型在函數提升和運行時機(解析時/運行時)上的差異。
當然我們最後要給一個總結:Javascript中函數聲明和函數表達式是存在區別的,函數聲明在JS解析時進行函數提升,因此在同一個作用域內,不管函數聲明在哪裡定義,該函數都可以進行調用。而函數表達式的值是在JS運行時確定,並且在表達式賦值完成後,該函數才能調用。這個微小的區別,可能會導致JS程式碼出現意想不到的bug,讓你陷入莫名的陷阱中。