我這裏就說說以下三種函數「聲明」的差別不一樣和應用場景。javascript
// 函數聲明 function A() {}; // 定義一個匿名函數並賦值給一個變量 var B = function() {}; // 定義一個具名函數並賦值給一個變量 var C = function D() {};
A()
。A 是一個標準的函數聲明語句。這行代碼明確地聲明瞭一個名爲A的函數。java
函數的聲明在解釋器解釋的過程當中,是在執行期前。也就是說,你的代碼還未執行前,這個函數就已經被聲明瞭。函數
因此 A 這種方式能夠後置聲明,例如ui
A();
function A(){};
這樣是不會出錯的。spa
B()
B 的整個過程是這樣的。首先聲明一個變量B
(這個是在執行期前),而後定義一個匿名函數表達式,最後B
指向這個匿名函數表達式。code
這種方式與 A 的區別在於,函數 B 是在執行期定義的。故這種方式去定義一個函數必須前置定義,不然在執行時會報類型錯誤——TypeError: undefined is not a function
。對象
還有就是,他是匿名函數,他是沒有函數名的。例如執行如下代碼:遞歸
// 如下代碼在非嚴格模式下能夠執行。嚴格模式會報錯 // 聲明 A function A() {console.log(arguments.callee.name)} // 執行他 A() // A; 控制檯裏面會輸出 // 定義 B var B = function() {console.log(arguments.callee.name)} // 執行他 B() // ;控制檯會輸出個空白行
C()
和 D()
這種狀況咱們以 ES5 標準來講,IE 的非標準實現不討論。ip
這種狀況同 B 很類似。可是函數表達式定義了一個具名函數。也就是說這個函數是有本身的名字的。作用域
可是這個名字卻不是綁定在當前做用域下的。故直接調用 D()
會出錯,以下
var C = function D() {} D(); // ReferenceError: D is not defined // D 未定義。
這個具名函數是爲了解決嚴格模式下本身調用本身的問題的。
var C = function D() { if(true) D() } C();
這樣就解決了前面的嚴格模式下不能訪問 arguments.callee
以遞歸調用本身的問題了。
知道區別了,咱們就能靈活運用來寫出優雅的代碼。