JavaScript IIFE (Immediately Invoked Function Expression)
An Immediately Invoked Function Expression (IIFE) is a JavaScript design pattern that allows you to define and execute a function immediately upon its declaration. It's a way of creating and running a function without explicitly naming or calling it:
(function() {
console.log('Hello World!');
})();
- A function expression is wrapped in parentheses:
(function() { ... })
. The parentheses are necessary because they turn the function declaration into a function expression. Without them, the JavaScript interpreter would treat it as a function declaration and throw a syntax error. - The final pair of parentheses:
()
. These parentheses are what actually call and execute the function. They're placed right after the function expression to invoke it immediately.
Practical Example of Using IIFE
Example:Counter Module
Suppose we want to create a simple counter module that exposes methods to increment and display the current count, without exposing the internal count variable. We can use IIFE to create a module that encapsulates the count and step and exposes the necessary methods.
const counter = (function() {
let count = 0;
let step = 1;
function increment(newStep) {
if(newStep) { step = newStep; }
count += step;
}
function display() {
console.log(`Current count: ${count}`);
}
return {
increment,
display
};
})();
counter.increment();
counter.display(); // prints: "Current count: 1"
counter.increment(3);
counter.display(); // prints: "Current count: 4"
counter.increment();
counter.display(); // prints: "Current count: 7"
Notice that any new increment value (newStep
) passed to the increment
function is being stored and used in subsequest increments (when no increment value is provided).
Example: One-time Event Listener
Suppose we want to add an event listener to a button that should only execute once and then remove itself - an IIFE can be used to create a self-contained event listener function:
<button id="myBtn">One time action</button>
(function() {
const btn = document.getElementById('myBtn');
if(!btn) { return; }
function handleClick() {
console.log('One time click done!');
btn.removeEventListener('click', handleClick);
}
btn.addEventListener('click', handleClick);
})();
Example: Configuration Setup
Imagine we have a configuration object that we need to set up with default values and some initial processing. We can use IIFE to create a self-contained setup function that initialises the configuration object:
const config = {};
(function() {
function setDefaults() {
config.apiKey = 'YOUR_API_KEY';
config.apiUrl = 'https://api.wooks.dev';
config.timeout = 5000;
}
// Initial config processing
function processSettings() {
console.log(`Configuring with API key: ${config.apiKey}`);
}
setDefaults();
processSettings();
})();
console.log(config);
// prints: { apiKey: 'YOUR_API_KEY',
// apiUrl: 'https://api.example.com',
// timeout: 5000 }
Why Use IIFE?
There are several reasons why you might want to use an IIFE in your JavaScript code:
- Encapsulation and scoping: IIFE creates a new scope, which means any variables declared within the function will not be accessible outside of it. This can help prevent variable name collisions and keeps the global scope clean.
- Privacy: Since variables and functions declared inside an IIFE are not accessible from outside, they remain private. This is useful when you want to create a module or a piece of code with a well-defined interface while hiding its internal implementation details.
- Self-contained code: IIFE can be useful when you want to create a self-contained piece of code that doesn't rely on external variables or functions. This can be helpful for code organization and maintainability.
Take away
IIFE is a powerful JavaScript pattern that provides encapsulation, privacy, and self-contained code. By understanding the syntax and use cases of IIFE, you can write cleaner, more maintainable, and more modular JavaScript code.