IIFEs in JavaScript — Use cases
Recently, I have come across IIFE’s in a library that used plain JavaScript in module pattern. They are used extensively in most of the JavaScript files that composed the library. I initially did not understand the reason why to have the constructor functions, many variables, and object definitions wrapped in a function expression(parentheses), until I was explained the most significant reason behind doing that by my colleague.
I assume that one is aware of how an IIFE (Immediately Invoked Function Expression) is formed and what it looks like. Nevertheless, I would state a simple example to get started.
(function () {
var message = "Hello there !!!";
})();
The above code is called an IIFE, and is immediately invoked as soon as it is defined. Note that it’s a Function Expression which is why the function that is wrapped inside the parentheses is anonymous. You might ask, why the parentheses. Try removing the parentheses and execute the function in browser’s console. It throws an error as the parser identifies it as an function declaration and function declarations cannot be anonymous.
Why do we need an IIFE? The most use case of an IIFE is to restrict the scope of variables to local so that they don’t pollute the global context. For example, compare the below two scenarios:
var loc = "global";
//Function declaration
function logger() {
console.log(loc); // logs global
console.log(window.loc); // logs global
}logger();---------------//Function Expression
(function () {
var loc = "global";
function logger() {
console.log(loc); // logs global
console.log(window.loc); // logs undefined
}logger();
}) ()
In the first example, the variable is declared outside the function, which makes it available globally and can be accessed and changed through the global object ( in browser, the global object is window & in Node, the global object is global).
To prevent it from happening where one might get access to all globally declared variables and can change them in browser’s console, the whole piece of code including variables, functions, objects , if present are wrapped inside an IIFE, which gets invoked immediately in a different execution context as shown in the second example. You might ask, if the variables are created in different execution context, won’t they be discarded as soon as the function gets invoked. Yes, they do. But that’s where closures come into picture and there are many ways to harness combined power of closures and IIFEs to design a modular application.
One typical use case of an IIFE and closure combination is to create a private state for any variable.
let reference = (function() {
let secret = "I cannot be changed by simple assignment";
return {
//ES5 new method syntax
change(value) {
secret = value;
},
get secret() {
return secret;
}
};
})();
console.log(reference.secret); // "I cannot be changed by simple assignment"
reference.change("I am changed");
console.log(reference.secret); // "I am changed"
In the above example, the secret value can only be changed by using the method as the variable is not available globally and is discarded off as soon the IIFE gets executed. Due to the power of closures in JS, the secret value is still preserved and is passed along with the object to the reference variable, making it available to the change method, when required.
NOTE: None of the above will make sense, if one does not understand what are closures and what is an execution context. If you wish, you can refer to MDN documentation or refer to concepts in You don’t know JS book series or any other source you may wish to refer.
Thank you for reading !! If there is anything in the article that needs tuning or clarifications or elaboration or correction, please mention it in the comments.