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
。 (但你已经猜到了,对吧?)