Why is it time to stop using JavaScript IIFE

The Immediately Invoked Function Expression (IIFE) function in JavaScript is a construct that allows you to call a function immediately after it is defined.

image

In this article, we will understand why it is worth abandoning the use of IIFE, despite its former merits.

We can declare variables inside autonomous blocks


Since the ES6 standard came into being, we can declare variables and constants inside a block with let and const. Along with this standard, it is also possible to allocate variables and constants into autonomous blocks that are not accessible from the outside.

For instance:

{
 let x = 1;
}

Then x will not be accessible externally. This is clearly better than:

(()=>{
 let x = 1;
})();

Now that ES6 is supported by almost all modern browsers, we must stop using IIFE to separate variables from the outside world. Another way to isolate variables is with modules that now have no problems supporting them either. Until we export them, they will not be available for other modules.

We can get rid of almost all closures


Closing is a mechanism by which a function remembers its external variables and can access them. If inside the function we create another and return it, then the returned function will be able to access external variables that are internal to the external function.

For example, here we can get some side effects:

const id = (() => {
 let count = 0;
 return () => {
   ++count;
   return `id_${count}`;
 };
})();

Again, now it makes no sense to fence this whole garden, since we have autonomous blocks and modules for data isolation. We can just put all this into our own module, then we will not need to worry about data access.

Closures cause side effects, which is not very good, as best practices and common sense instruct us to avoid them whenever possible. They make it difficult to test functions that are not clean in this case.

In addition, you should not produce nested functions when this can be avoided: with them, the code becomes more confusing than without them.
The best alternative is to replace them with modules:

let count = 0;
export const id = () => {
 ++this.count;
 return `id_${count}`
}

In the above code, we have the same declaration for the count variable and export the id () function so that it is available to other modules. So we hide count and open id (), as we wanted, only without using IIFE. As a result, we get less nesting and get rid of the need to define another function and run it.

We can create aliases for variables differently.


We could write this:

window.$ = function foo() {
 // ...
};(function($) {
 // ...
})(jQuery);

But now there is no need to use IIFE to create aliases. Using modules, we can simply import a variable under a different name, thereby creating an alias for it.

And then just write:

import { $ as jQuery } from "jquery";
const $ = () => {};

In addition, you should not add new properties to the window object, since this pollutes the global scope.

We can easily get a global object.


With the advent of globalThis, we don’t have to worry about the name of the global object in various environments as it becomes the standard.

We could use IIFE to capture a global object:

(function(global) {
 // ...
})(this);

But now this is not necessary. Yes, and before, you could do without this, simply by writing the following line:

const globalObj = self || window || global;

To be more precise, you can write this:

const getGlobal = () => {
 if (typeof self !== 'undefined') { return self; }
 if (typeof window !== 'undefined') { return window; }
 if (typeof global !== 'undefined') { return global; }
 throw new Error('unable to locate global object');
};

And then you can not add an additional function call and nesting that appear when using IIFE.

We can make minification easier


With JavaScript modules, we no longer need to separate the rest of the code from IIFE in order to minify our files properly.

Webpack, Browserify, Parcel, Rollup and so on can work with modules properly, so we must use them to create cleaner code.

Conclusion


It's time to stop using IIFE in our code. This adds extra functionality and redundant nesting.

In addition, now this is an anachronism: IIFE was used even before the advent and widespread use of modules in JavaScript. In 2020, we must use modules and autonomous blocks to separate the code.

To prevent external access to variables inside the module, we can use block scopes.


All Articles