Immediately invoked function expressions (IIFE), which are also known as self invoked functions, are blocks of code which are defined and executed immediately after creation. The function inside can use the function keyword (traditional way) or be an arrow function. Either way, the entire function is surrounded by a set of parentheses followed by another pair of parentheses. This second pair of parentheses is the invocation operator which allows the function to be immediately executed.
Traditional syntax with function declaration
(
function () {
console.log('IIFE called')
}
)();
Arrow function syntax
(
() => console.log('IIFE with arrow function called')
)();
Now that we know what an IIFE is, the next question is why is it useful? Here are some use cases.
- Avoid polluting the global namespace by creating a new scope
- To create closures with private variables
- It is used to execute async and await functions
- Creation of modules
As a matter of fact a significant part of my day job is performing automation testing using Puppeteer. These Puppeteer scripts are giant IIFEs (typically a few thousand lines long) which run code which tests the user interface (UI) of our applications. Anyway, let us continue to discuss our use cases.
Avoid pollution of the global namespace
What does this mean? Essentially it means avoiding name collision between global and local variables of the same name. This becomes more apparent in large enterprise applications where the possibility of reusing variable names increases, especially with multiple developers working on the same application. The example below illustrates this point.
//Global scope
const value = "This variable is in global scope and is called 'value'.";
const stateLocation = () => console.log("Now in global scope");
stateLocation();
console.log(value);
console.log("*********************************************************");
(
function () {
//Function scope
const value = "This variable is in function scope and avoids global pollution even though the variable name 'value' is reused";
const stateLocation = () => console.log("Now in function scope of IIFE");
stateLocation();
console.log(value);
}
)();
Once this code is executed the output is as follows:
Now in global scope
This variable is in global scope and is called 'value'.
*********************************************************
Now in function scope of IIFE
This variable is in function scope and avoids global pollution even though the variable name 'value' is reused
To create closures with private variables
Recall that a closure is an inner function that has access to variables in the outer function scope. This example of an IIFE which calculates the area of a circle illustrates this point. Furthermore, the variable in the outer function is private because it is inaccessible outside of the function.
const areaOfCircle = (
function () {
const pi = Math.PI //private variable
return function (radius) { //closure with access to outer scope private variable
return pi * (radius ** 2)
}
}
)();
const areaWithRadius2 = areaOfCircle(10);
console.log('Area of a circle with a radius of 10 is ', areaWithRadius2);
// console.log('PI = ', pi); //ReferenceError: pi is not defined
Output:
Area of a circle with a radius of 10 is 314.1592653589793
Use to execute the async and await function
IIFEs are also useful for executing asynchronous operations such as network calls. The following example fetches a list of todos from an mock server.
(
async function () {
const response = await fetch('https://dummyjson.com/todos');
const todosObject = await response.json();
const todoList = todosObject.todos.map(todo => todo.todo);
console.log(todoList);
}
)();
Creation of modules
Here is a module which performs operations using basic physics equations. It can be exported and used by other programs. I will discuss this further in another article Building a Command Line Physics Calculations Application with an IIFE Module Pattern. Note the use of private variables and closures.
export const physicsCalculations = (
function () {
//the below constants are private variables
const g = 9.80665; //gravity constant in meters/second squared
const c = 299792458; //speed of light in m/s
//functions to be returned as methods in this module
const velocity = (distance, time) => distance / time;
const acceleration = (speed, time) => speed / time;
const potentialEnergy = (mass, height) => mass * g * height;
const momentum = (mass, speed) => mass * speed;
const energy = (mass) => mass * (c ** 2);
const force = (mass, acc) => mass * acc;
const kineticEnergy = (mass, speed) => 0.5 * mass * (speed ** 2);
//object containing named methods including two getter methods
return {
velocity,
acceleration,
potentialEnergy,
momentum,
energy,
force,
kineticEnergy,
getSpeedOfLight: () => c,
getGravityConstant: () => g
}
}
)();
As one can see there are a myriad of use cases for IIFEs. It can make data more secure by encapsulating of data as well as adding modularity to applications.
Top comments (0)