How to Use an IIFE in Javascript
Javascript
What Is an IIFE?
A Javascript IIFE (immediately invoked function expression) provides a means of defining and executing a function within a single expression.
Let’s see an example:
(async () => {
const userId = store.getUserId();
const date = new Date();
await fetchUser(userId, date);
})();
Here we have created an IIFE. It simply finds the user ID and the current datetime before making an asynchronous request for a user object. As fetchUser
is being await
ed, we have marked the inner function as async
.
While this syntax may look unfamiliar at first, we can quickly see an IIFE is composed of two clear components:
-
The content between the first pair of parentheses. This is the function that will be executed. Note that this function required no name, hence IIFEs are also often referred to as (self-executing) anonymous functions.
-
The final pair of parentheses. This is what instructs Javascript to (immediately) execute the code in (1).
In fact, the code above is effectively the equivalent of:
const loadUser = async () => {
const userId = store.getUserId();
const date = new Date();
await fetchUser(userId, date);
};
loadUser();
See that we have replaced the inline function in (1) with the name of a separately defined function.
Note that, in our first example, the execution of the IIFE as a whole was not await
ed (that is, instructions below the IIFE would not wait upon the completion of fetchUser()
). As such, to simulate equivalent behaviour in this example, we have not await
ed the invocation of loadUser()
, despite the function being technically asynchronous.
Should You Use an IIFE?
Now that we know how to use an IIFE, it might be a good time to question whether we should use an IIFE. Well, in my opinion, probably not:
-
IIFEs utilise syntax that may strike some as unusual or unfamiliar, making them harder to read than the traditional approach of separating function definition and invocation.
-
By being anonymous (nameless), IIFEs don’t benefit from the contextual information provided by a named function.
That said, there may be a (narrow) set of use-cases where IIFEs are handy. Two of the most common are:
-
We need to introduce a new local scope to avoid polluting or interfering with the outer/global scope. In our example above, the variables
userId
anddate
are scoped to the IIFE. Of course, creating a separate function achieves the same effect, so this only applies when defining said function would prove substantially inconvenient or unnecessary. -
Some Javascript runtimes do not allow
await
at the top-level of a module. In this case, an IIFE may prove useful, though I find this problem is increasingly less prevalent, particularly in the context of frameworks like Vue and React.