一、定義函數的三種方法
1、函數聲明
function 函數名稱(參數:可選){/**函數體**/}
2、函數表達式(2種)也叫函數字面量
var f = function(){} //沒有函數表示標識符
var f = function fun(){} //有函數表示符fun ,即命名函數表達式
3、構造函數法
var sum = new Function('a','b','return a+b;'); //參數必須加引號
今天暫時不講關於這三種方法的區別,我們直奔主題。
二、命名函數表達式
如今很少有人用這種寫法了,但當看到這個命名函數表達式的時候,我腦海中仍然會浮現很多想法。命名函數表達式有什么用?又會存在什么樣的坑?
1、可以用f()調用該命名函數表達式,fun只是一個標識符,不能調用函數。

2、標識符fun只有在函數作用域中有效,在外面的作用域中無效。
這倒是可以用在遞歸上面,比如改寫經典的兔子問題。
var foo = function f(n){
if(n==1||n==2){
return 1;
}else{
return f(n-1)+f(n-2)} //只能在函數內部使用
}
console.log(foo(10));
可以使用arguments.callee代替上面的f函數標識符,假如在函數里面不小心把f賦值了,那可不是。。。。但是嚴格模式下,arguments.callee又是失效的。扯一個遠一點話題。看看遞歸是多么消耗內存。(我的瀏覽器但是chrome58)上面兔子問題的代碼,傳入參數為45,看看cpu飈到多少,傳入參數50,瀏覽器直接掛了,可能我開的有點多了。所以啊,遞歸 。。。。

3、那命名函數表達式應用
沒有命名的函數表達式在實際應用中很常見,比如不希望函數聲明提前的,特別是在一些初始換函數情況下,可以考慮用函數表達式。那么嗎,命名的函數表達式一般有什么用呢?
如果函數都有一個名字,那么調用棧就會顯示被調用函數的函數名,這樣在調試時候就不比較明朗。

4、說好的坑呢?
var f= function fun(){};
typeof fun; // "function" IE8下
這樣就會把把標識符泄露到外面,不過在現代瀏覽器不會這樣的,不要擔心。
最后說一句
坑無處不在,走多了就變成路了
