What are Immediately Invoked Function Expressions (IIFE)?
An Immediately Invoked Function Expression (IIFE) is a JavaScript function that runs as soon as it is defined. It is a design pattern which is also known as a Self-Executing Anonymous Function and contains two primary parts: the function expression itself and the immediate invocation using the `()` operator. IIFEs are primarily used to create a private scope for variables, thus preventing global scope pollution and ensuring data privacy.
Definition
An IIFE is a function expression that is executed immediately after its creation. The term "immediately invoked" refers to the fact that it is called right after its definition, rather than waiting for an explicit call. The "function expression" part means that it's treated as a value, often an anonymous function.
Syntax
The common syntax for an IIFE involves wrapping a function expression in parentheses () and then immediately following that with another set of parentheses () to invoke it. The outer parentheses () are crucial because they turn the function declaration into a function expression, which can then be immediately invoked.
(function() {
// Code inside the IIFE
})();
// Alternative syntax (less common but valid):
(function() {
// Code inside the IIFE
}());
// Using arrow functions for IIFEs (ES6+):
(() => {
// Code inside the IIFE
})();
Why Use IIFEs?
- Scope Isolation / Data Privacy: This is the primary reason. Variables declared inside an IIFE are not accessible from the outside. This prevents polluting the global scope with temporary variables and avoids naming collisions, especially in larger applications or when integrating third-party libraries.
- Avoiding Variable Hoisting Issues: By encapsulating code within an IIFE, variables declared with
varinside it are scoped to the IIFE, preventing them from being hoisted to a higher (e.g., global) scope than intended. - Creating Private Variables and Closures: IIFEs can be used to create private variables that are only accessible within the function, often by returning an object with methods that have access to these private variables through closures. This is fundamental to the module pattern.
- Executing Code Once: If you have initialization code that needs to run only once and then dispose of its temporary variables, an IIFE is perfect for this.
- Module Pattern Implementation: Before native ES6 modules, IIFEs were widely used to implement the module pattern, allowing developers to create self-contained modules with private and public members.
Examples
Basic IIFE for Scope Isolation
var globalMessage = "Hello from global!";
(function() {
var localMessage = "Hello from IIFE!";
console.log(localMessage); // Output: Hello from IIFE!
console.log(globalMessage); // Output: Hello from global!
})();
// console.log(localMessage); // ReferenceError: localMessage is not defined
IIFE with Parameters
(function(name) {
console.log("Hello, " + name + "!");
})("Alice"); // Output: Hello, Alice!
(function(length, width) {
var area = length * width;
console.log("Area is: " + area);
})(10, 5); // Output: Area is: 50
IIFE Returning a Value
var counter = (function() {
var count = 0;
return {
increment: function() {
count++;
return count;
},
decrement: function() {
count--;
return count;
},
getValue: function() {
return count;
}
};
})();
console.log(counter.getValue()); // Output: 0
console.log(counter.increment()); // Output: 1
console.log(counter.increment()); // Output: 2
console.log(counter.decrement()); // Output: 1
// console.log(counter.count); // undefined (count is private)
Using IIFE in a Loop (pre-ES6 `let`)
Before let introduced block-scoping, IIFEs were crucial to capture the correct value of a loop variable for asynchronous operations.
// Problem without IIFE (all timeouts would log '3')
// for (var i = 0; i < 3; i++) {
// setTimeout(function() {
// console.log(i);
// }, 100 * i);
// }
// Solution with IIFE
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 100 * j);
})(i);
}
// Output: 0 (after 0ms), 1 (after 100ms), 2 (after 200ms)