談談函數的定義

我這裏就說說以下三種函數「聲明」的差別不一樣和應用場景。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 以遞歸調用本身的問題了。

總結

知道區別了,咱們就能靈活運用來寫出優雅的代碼。

  • 若是想後置函數的聲明,咱們就能夠用 A;
  • 若是我只是想生成一個匿名函數把他設置爲某個對象的屬性,那就用 B;
  • 若是 B 知足不了我,我還要遞歸調用本身,那就用 C/D。
相關文章
相關標籤/搜索