深入學習JavaScript系列學習筆記(二)——命名函數表達式

1、函數聲明與函數表達式

       函數聲明:

  function 函數名稱 (參數:可選){ 函數體 }

  函數表達式(函數語句):

  function 函數名稱(可選)(參數:可選){ 函數體 }

function foo(){} // 聲明,因爲它是程序的一部分
  var bar = function foo(){}; // 表達式,因爲它是賦值表達式的一部分

  new function bar(){}; // 表達式,因爲它是new表達式

  (function(){
    function bar(){} // 聲明,因爲它是函數體的一部分
  })();

如果不聲明函數名稱,則肯定是函數表達式,但如果聲明瞭函數名稱,如何判斷是函數聲明還是函數表達式?

ECMAScript是通過上下文來區分的,如果function 函數名稱(){}是作爲賦值表達式的一部分的話,那它就是一個函數表達式,如果function 函數名稱(){}被包含在一個函數體內,或者位於程序的最頂部的話,那它就是一個函數聲明。

函數表達式和函數聲明的差別:函數聲明在任何表達式解析和求值之前先被解析和求值。如:

alert(fn());

  function fn() {
    return 'Hello world!';
  }

函數聲明在條件語句內雖然可以用,但是沒有被標準化,也就是說不同的環境可能有不同的執行結果,所以這樣情況下,最好使用函數表達式:

// 千萬別這樣做!
  // 因爲有的瀏覽器會返回first的這個function,而有的瀏覽器返回的卻是第二個

  if (true) {
    function foo() {
      return 'first';
    }
  }
  else {
    function foo() {
      return 'second';
    }
  }
  foo();

  // 相反,這樣情況,我們要用函數表達式
  var foo;
  if (true) {
    foo = function() {
      return 'first';
    };
  }
  else {
    foo = function() {
      return 'second';
    };
  }
  foo();

小結:函數聲明只能出現在程序或函數體內。它不能出現在if、for、while等Block內。Block塊內只能含有Statement語句。

同時因爲函數表達式不能以function開頭,故函數表達式同樣不能出現在Statement語句和Block塊內。

2、語句函數

在ECMAScript的語法擴展中,有一個是函數語句,目前只有基於Gecko的瀏覽器實現了該擴展,一般來說不推薦使用

函數語句和函數表達式的區別:

一般語句能用的地方,函數語句也能用,當然也包括Block塊中。

函數語句不是在變量初始化期間聲明的,而是在運行時聲明的——與函數表達式一樣。不過,函數語句的標識符一旦聲明能在函數的整個作用域生效了。(聲明函數——函數,函數表達式——表達式,語句函數——函數)

函數表達式的新名字只能在函數內部作用域內有效,外部作用域無效。

var f = function foo(){
    return typeof foo; // foo是在內部作用域內有效
  };
  // foo在外部用於是不可見的
  typeof foo; // "undefined"
  f(); // "function"

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章