Function構造函數、 函數聲明 、 函數表達式 的區別

對比下面的例子:前端

Function構造函數

var multiply = new Function('x', 'y', 'return x * y');
複製代碼

函數聲明

function multiply(x, y) {
   return x * y;
} // 沒有分號
複製代碼

函數表達式

var multiply = function(x, y) {
   return x * y;
 };
複製代碼

一個命名爲func_named的函數的函數表達式,被賦值給變量multiply:

var multiply = function func_name(x, y) {
   return x * y;
};
複製代碼

區別

  • 函數名不能被改變,但函數的變量卻可以被再分配
  • 函數名只能在函數體內使用
  • 假若在函數體外使用函數名將會致使錯誤(若是函數以前是經過一個var語句聲明的則是undefined)。如:
var y = function x() {};
alert(x); // throws an error
複製代碼
  • 函數名和函數的變量存在着差異。函數名不能被改變,但函數的變量卻可以被再分配。函數名只能在函數體內使用。假若在函數體外使用函數名將會致使錯誤
  • 函數名與被函數賦值的變量是不相同的. 彼此之間沒有關係
  • 函數聲明同時也建立了一個和函數名相同的變量
  • 使用 'new Function'定義的函數沒有函數名。在 SpiderMonkey JavaScript引擎中,其函數的序列化形式表現的好像它擁有一個名叫"anonymous"的名稱同樣,而實際上其函數並無名稱,anonymous 不是一個能夠在函數內被訪問到的變量
  • 和函數表達式或者Function構造函數定義的函數不一樣,函數聲明的函數能夠在它被聲明以前使用。如:
// 函數聲明
foo() // foo
function foo() {
    return 'foo'
}
// 函數表達式
foo2() // foo2 is not a function
var foo2 = function(){
    return 'foo2'
}
// Function 構造函數  
foo3()  // foo3 is not a function
var foo3 = new Function('return "foo3"')

複製代碼
  • 函數表達式定義的函數繼承了當前的做用域。換言之,函數構成了閉包。另外一方面,Function構造函數定義的函數不繼承任何全局做用域之外的做用域(那些全部函數都繼承的)。bash

  • 經過函數表達式定義的函數和經過函數聲明定義的函數只會被解析一次,而Function構造函數定義的函數卻不一樣。閉包

注意在經過解析Function構造函數字符串產生的函數裏,內嵌的函數表達式和函數聲明不會被重複解析。例如:ide

var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo(); // 函數體字符串"function() {\n\talert(bar);\n}"的這一部分不會被重複解析。
複製代碼

函數聲明如何轉成函數表達式

  • 成爲表達式的一部分
// 函數表達式
var foo = function(){}
var bar = function bar(){}
(function bar2() {})
複製代碼
  • 再也不是函數或者腳本自身的「源元素」 (source element)。「源元素」是腳本或函數體中的非嵌套語句
var x = 0;               // source element
if (x === 0) {           // source element
   x = 10;               // 非source element
   function boo() {}     // 非 source element 函數表達式
}
function foo() {         // source element   函數聲明
   var y = 20;           // source element
   function bar() {}     // source element   函數聲明
   while (y === 10) {    // source element
    function blah() {} // 非 source element 函數表達式
     y++;               //非source element
   }
}
複製代碼

若有侵權,請發郵箱至wk_daxiangmubu@163.com 或留言,本人會在第一時間與您聯繫,謝謝!! 函數

關注咱們
長按二維碼關注咱們,瞭解最新前端資訊
相關文章
相關標籤/搜索