I’m learning JavaScript and I understand the general function types, closures, etc. But with IIFEs my initial reaction was “if its immediately invoked, why not just inline it”. So I went and read this article that describes “4 Practical Use Cases” for IIFEs. However, two of which are related to circumventing the scoping issues that come with var
s (which are no longer a concern post ES6 with let
and const
being introduced). A third one deals with global variable naming conflicts (what namespaces generally deal with in C++). And, from what I can tell, Import Aliasing (which was also introduced in ES6) solves this problem.
The remaining use case is regarding closures:
The author claims that combining a closure with an IIFE provides us with “two great benefits”: 1) the scopes of variables is secured, and 2) you can modify variables inside a function from the outside. However, from my understanding of closures, you can have both those benefits with just a regular closure.
For instance,
const IIFEclosure = (() => { let v = 10; return { value: _ => v, set: newValue => v = newValue, }; })(); const handle = () => { let v = 10; return { value: _ => v, set: newValue => v = newValue, }; }; const closure1 = handle(); const closure2 = handle(); console.log(IIFEclosure.value(), closure1.value(), closure2.value()) // 10 10 10 IIFEclosure.set(20); closure1.set(30); closure2.set(40); console.log(IIFEclosure.value(), closure1.value(), closure2.value()) // 20 30 40
The only difference I can see here is that you can create multiple instances of the regular closure using handle
while with IIFEclosure
there can be only one since its immediately invoked in place and has no “handle”. I guess it has the upside of not polluting the namespace with an extra variable name. I am not sure if in practice having a closure that can only be instantiated once is useful or not. But, other than that, as far as I can tell, both benefits mentioned above are satisfied in both examples.
So if my above reasoning is valid, this leads me to opening question; what, if any, are the benefits/usecases of IIFEs in post ES6 JavaScript?
Advertisement
Answer
For closures there is still a small advantage: the function itself can be anonymous, avoiding one (function) variable. For instance, in your example, the non-IIFE has the handle
as extra variable. If you want to minimise the littering of the current scope (maybe even the global scope) then IIFEs are still useful.
I also find IIFE useful at the top level for using await
— although that would be named an IIAFE:
(async () => { const response = await fetch("...."); const object = await response.json(); // ... const result = await lookup(object.id); // ... })();
Since ECMAScript 2022 introduced top-level await, it is no longer needed to have such async
wrappers in modules.
As to the use case of global name aliasing, that one can also be solved with a plain block:
{ const $ = jQuery; // Here comes $-referencing code that will not conflict with "outside" $ use. }