I have been tinkering with JS module bundling at Netflix and found IIFEs are a recurring pattern in JS Modules. IIFEs, pronounced as iffy, stands for Immediately-Invoked Function Expression.
I also realized that a lot of javascript developers are uncomfortable working with IIFEs. This post is an attempt to help javascript engineers understand the potentially complex concept behind IIFE.
What Exactly Is an IIFE
An Immediately-invoked Function Expression (IIFE) is a way to execute functions immediately, as soon as they are created. So a simple IIFE could be:
(function () { /* Simple IIFE! */ })();
If you look at the code closely, we have a function defined inside parentheses, and then we append
()
to invoke that function.// function definition inside a parentheses (function () { /* Simple IIFE! */ })(); // <-- invoke that function here.
The wrapping parentheses around the function definition is needed. It tells the parser to treat the function definition as an expression. When the javascript parser encounters the function keyword, it knows to parse it as a function expression and not a function declaration.
The final
()
just invokes this expression.Why Do We Need IIFE
In Javascript, whenever we invoke a function, we create a new execution context. Any variable (or even new functions) defined within an invoked function can only be accessed inside (and never from outside) that context. This means, invoking a function gives us a way to create something that resembles private variables.
In simple words:
IIFE allows us to define an isolated scope and execute code in this scope
Can IIFEs Return Something?
The answer is - Yes, IIFEs can return objects, functions... anything.
Consider the following example:
// Create an anonymous function expression that gets invoked immediately, // and assign its *return value* to a variable. var counter = (function () { var i = 0; return { get: function () { return i; }, set: function (val) { i = val; }, increment: function () { return ++i; }, }; })(); // `counter` is an object with properties, which in this case happen to be // methods - `get`, `set` and `increment` counter.get(); // 0 counter.set(3); counter.increment(); // 4 counter.increment(); // 5 counter.i; // undefined (`i` is not a property of the returned object) i; // ReferenceError: i is not defined (it only exists inside the closure)
In this example, it is easy to see how IIFE returned an object which exposes some functionalities.
The Module Pattern
A Module is a re-usable, self contained collection of code that
- exposes distinct functionalities, that its consumers can use
- never exposes private information
The
counter
IIFE above returns an object with functionalities, which in this case happen to be methods - get
, set
and increment
, and is capable of hiding the implementation detail (in this case - variable i
).The
counter
created in the previous code example is a perfect example of a Module!IIFEs allows us to create modules and this approach is called
The Module Pattern
With very little code, we managed to namespace related methods and properties and minimized global scope pollution and create private variables.
Thats the power of IIFEs.