立即调用的函数表达式或 IIFE 是在定义函数后立即运行的函数。您可能还会看到人们将它们称为匿名函数。它们为我们提供了一种简单的方法来隔离函数中的变量,而不是全局变量 - 之后我们可以轻松地立即运行函数。当顶级不可用时,它们对于运行异步函数也很有用。await
虽然我们通常定义这样的函数:
let x = () => { console.log("hello"); } let y = function() { console.log("world"); } function z() { console.log("!"); } x(); y(); z();
定义 IIFE 意味着在我们编写函数时调用它。因此,我们可以像这样定义IIFE:
(function() { console.log("hello world!") })()
此函数是匿名的(它没有名称) - 它会立即运行。您也可以使用箭头表示法运行它,如下所示:
(() => { console.log("hello world!") })()
虽然上面的IIFE没有名字,但你可以给它们起名字。但是,这并没有真正的意义,因为您无法在其他任何地方调用它们。以这种格式创建并调用函数后,就不能在其他任何地方使用它。这意味着在下面的示例中,尝试调用其他地方将不起作用:myFunction()
(function myFunction() { console.log("hello world!") })()
匿名或立即调用的函数表达式可用于封装异步行为。您仍然可以使用关键字使 IIFE 异步:async
(async () => { console.log("hello world!") })()
我们可以使用预期的格式将变量直接传递到 IIFE 中。例如,下面我们在 IIFE 中有一个参数 - 就是。我们可以使用最后一组括号传入一个值:x
x
let getNumber = 10; (function(x) { console.log(x + 10) })(getNumber) // console logs 20
You may sometimes see the following code when IIFEs are defined where a semi colon is added to the start.
;(() => { return 10; })
这似乎令人困惑,但它是为了避免一个奇怪的问题,即如果前一行没有分号,函数最后一行将用作函数名称。请考虑以下代码:
let b = 5 let c = 10 let a = b + c (function () { return 10 })();
如果有人忘记加分号,或者您将 IIFE 导入到前一行不包含分号的行上,您可能会遇到一些奇怪的错误。在上面的示例中,你将收到错误。这是因为代码将此解释为尝试运行函数。本质上,代码看到的是:let a = b + c
Uncaught TypeError: c is not a function
c
c(() => { return 10 })()
因此,在 IIFE 开头使用防御分号是避免这种情况的简单方法。
IIFE常见于Javascript代码库中,并且是执行许多操作的有用方法,例如异步代码和作用域变量或特定功能块中的代码。虽然现在在Javascript中还有其他方法可以实现这一点,但你仍然会在任何地方看到这些方法——所以了解它们是如何工作的是很重要的。