在JavaScript中,函數宣告和函數表達式都是使用function關鍵字來建立函數的,是不是覺得它們很像,很容易混淆。以下這篇文章就來帶大家分析一下函數表達式和函數聲明,介紹一下函數表達式和函數宣告的差別。
在 JavaScript 中,function
關鍵字可以完成一個簡單的工作:建立一個函數。但是,使用關鍵字定義函數的方式可以建立具有不同屬性的函數。
在本文中,我們來看一下,如何使用function
關鍵字來定義函數宣告和函數表達式,以及這兩個函數之間的差異又是什麼。
函數宣告和函數表達式是使用 function
關鍵字建立函數的2種方法。
舉個例子來說明差異,我們建立兩個版本的sums 函數:
function sumA(a, b) { return a + b; } (function sumB(a, b) { return a + b; }); sumA(1, 2); // ??? sumB(1, 2); // ???
動手試試:https://jsfiddle.net/dmitri_pavlutin/8b46yokr/2/
一般情況,像往常一樣定義函數(sumA函數
)。在另一種情況下,函數被放置在一對括號中(sumB函數
)。
如果呼叫 sumA(1,2)
和 sumB(1,2)
會發生什麼事?
如預期的那樣,sumA(1, 2)
傳回 3
。但是,呼叫sumB(1, 2)
會引發例外:Uncaught ReferenceError: sumB is not defined
。
原因是sumA
是使用函數宣告建立的,該函數宣告在目前作用域中建立函數變數(具有與函數名稱相同的名稱)。但是sumB
是使用函數表達式建立的(將其包裝在括號中),該函數表達式不會在目前作用域內建立函數變數。
如果你想存取使用函數表達式建立的函數,那麼將函數物件儲存到一個變數中:
// Works! const sum = (function sumB(a, b) { return a + b; }); sum(1, 2); // => 3
如果語句以`function
`關鍵字開頭,則為函數聲明,否則為函數表達式。
// 函数声明:以`function`关键字开头 function sumA(a, b) { return a + b; } // 函数表达式:不以`function`关键字开头 const mySum = (function sumB(a, b) { return a + b; }); // 函数表达式:不以`function`关键字开头 [1, 2, 3].reduce(function sum3(acc, number) { return acc + number });
從更高的角度來看,函數宣告對於建立獨立函數很有用,但是函數表達式可以用作回呼。
現在,我們更深入地研究函數宣告和函數表達式的行為。
在前面的範例中已經看到的,sumA
是一個函數宣告:
// Function declaration function sumA(a, b) { return a + b; } sumA(4, 5); // => 9
當一個語句包含function
關鍵字,後面跟著函數名稱,一對帶參數的括號(param1, param2, paramN)
以及包圍在一對花括號{}
中的函數主體時,就會發生函數宣告。
函數宣告會建立一個函數變數:一個與函數名稱同名的變數(例如,上一個範例中的sumA
)。在目前作用域中(在函數宣告之前和之後),甚至在函數作用域本身內,都可以存取該函數變數。
函數變數通常用於呼叫函數或將函數物件傳遞給其他函數(傳遞給高階函數)。
例如,寫一個函數sumArray(array)
,以遞歸方式累積一個陣列的項(該陣列可以包含數字或其他陣列):
sumArray([10, [1, [5]]]); // => 16 function sumArray(array) { let sum = 0; for (const item of array) { sum += Array.isArray(item) ? sumArray(item) : item; } return sum; } sumArray([1, [4, 6]]); // => 11
#動手試試:https://jsfiddle.net/dmitri_pavlutin/n7wcryuo/
function sumArray(array) { ... }
# 是函數宣告。
包含函數物件的函數變數sumArray
在目前作用域中可用:sumArray([10, [1, [5]]])
之前和sumArray([1, [4, 6]])
之後,函數聲明, 以及函數本身的作用域sumArray([1, [4, 6]])
(允許遞歸呼叫) 。
由於提升,函數變數在函數宣告之前可用。
2.1 函數宣告的注意事項
函數宣告語法的作用是建立獨立函數。函數宣告應在全域作用域內,或直接在其他函數的作用域內:
// Good! function myFunc1(param1, param2) { return param1 + param2; } function bigFunction(param) { // Good! function myFunc2(param1, param2) { return param1 + param2; } const result = myFunc2(1, 3); return result + param; }
基於相同的原因,不建議在條件(if
)和迴圈(while
,for
)中使用函數宣告:
// Bad! if (myCondition) { function myFunction(a, b) { return a * b; } } else { function myFunction(a, b) { return a + b; } } myFunction(2, 3);
使用函數表達式更好地執行有條件地建立函數。
當function
關鍵字在表達式內部建立函數(有或沒有名稱)時,將出現函數表達式。
以下是使用表達式建立的函數的範例:
// Function expressions const sum = (function sumB(a, b) { return a + b; }); const myObject = { myMethod: function() { return 42; } }; const numbers = [4, 1, 6]; numbers.forEach(function callback(number) { console.log(number); // logs 4 // logs 1 // logs 1 });
在函數表達式中建立了兩個函數:
function(){return 42}
,那是匿名函數表達式sumB
和回調,那麼這是一個命名函數表達式3.1 函數表達式的注意事項
函數表達式適合作為條件創建的回調或函數:
// Functions created conditionally let callback; if (true) { callback = function() { return 42 }; } else { callback = function() { return 3.14 }; } // Functions used as callbacks [1, 2, 3].map(function increment(number) { return number + 1; }); // => [2, 3, 4]
如果已建立命名函數表達式,請注意,該函數變數僅在建立的函數作用域內可用:
const numbers = [4]; numbers.forEach(function callback(number) { console.log(callback); // logs function() { ... } }); console.log(callback); // ReferenceError: callback is not defined
试一试:https://jsfiddle.net/dmitri_pavlutin/sujwmp10/2/
callback
是一个命名的函数表达式,因此callback函数变量仅在callback()
函数使用域可用,而在外部则不可用。
但是,如果将函数对象存储到常规变量中,则可以在函数作用域内外从该变量访问函数对象:
const callback = function(number) { console.log(callback); // logs function() { ... } }; const numbers = [4]; numbers.forEach(callback); console.log(callback); // logs function() { ... }
试一试:https://jsfiddle.net/dmitri_pavlutin/1btmrcu2/1/
根据使用function
关键字创建函数的方式,可以通过两种方法来创建函数:函数声明和函数表达式。
留个问题: function sum(a, b) { return a + b } + 1
是函数声明还是函数表达式,可以在留言中说出你的答案。
英文文章地址:https://dmitripavlutin.com/javascript-function-expressions-and-declarations/
作者:Dmitri Pavlutin
更多编程相关知识,请访问:编程视频!!
以上是JS中函數表達式 VS 函數聲明,聊聊它們的不同點的詳細內容。更多資訊請關注PHP中文網其他相關文章!