let speak = function() { return 'Hi'; } // anonymous function expression
let speak = function speakFn() { return 'Hi'; } // named function expression
let speak = async function() { await sleep(1000); return 'Hi'; } // anonymous asynchronous function expression
let speak = async function speakFn() { await sleep(1000); return 'Hi'; } // named asynchronous function expression
在 Javascript 中建立函數有四種方法。在 Javascript 中還有四種建立非同步函數的方法,它們是彼此精確的鏡像。
為了示範這是如何運作的,我使用了一個簡單的
sleep
函數,在全域宣告:函數宣告
這是宣告函數最簡單的方法。它可以聲明一次並提升到目前函數作用域的頂部。
函數宣告和非同步函數宣告完全相同,只是
async
函數總是傳回一個 Promise 並允許您使用await
。函數表達式
函數表達式看起來非常像函數宣告。然而,它們並沒有被提升到函數作用域的頂端。您可以根據需要多次重新定義它們。它們可以內聯定義。它們可以是匿名的,也可以是命名的:如果它們被命名,那麼名稱引用該函數範圍內的函數。
函數表達式和非同步函數表達式完全相同,只是
async
函數總是傳回一個 Promise 並允許您使用await
。箭頭函數
箭頭函數是一種快速且簡短的方法定義一個函數,在 ES2015 (ES6) 中引入。它們在大多數方面與函數表達式等效,只是它們始終是匿名的,並且
this
的值始終是詞法綁定的,即從外部作用域繼承。箭頭函數和非同步箭頭函數完全相同,只是
async
函數總是傳回一個 Promise 並允許您使用await
。 (它們在上面的語句中略有不同,因為每個非同步函數內部都有多個語句。這表示這些語句需要包含在一個區塊{}
中,並且return
需要是明確的。這也是正確的超過一條語句長度的普通箭頭函數。)函數建構子
函數建構函數可讓您使用字串動態定義函數。請注意,它們始終在全域範圍內運行,並且無法存取定義它們的範圍。它們僅在極少數情況下有用。我個人不認為非同步函數構造函數會有什麼用處。 ES2017的作者同意我的觀點,因為
AsyncFunction
不是全域對象,必須先使用const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
取得。使用函數建構函式建立的函式和使用匿名函式建構函式建立的函式完全相同,只是
async
函式總是傳回一個 Promise 並允許你使用await
。 (但你已經猜到了,對吧?)