JavaScript Tutorial
Master IIFE to create private scopes and implement the module pattern.
Why this matters
IIFE is a powerful pattern for code organization and encapsulation. Understanding IIFE is essential for reading existing code and implementing the module pattern.
What is IIFE?
IIFE stands for Immediately Invoked Function Expression. It's a function that runs immediately after it's defined. The main purpose is to create a private scope and avoid polluting the global namespace.
IIFEs were especially important before ES6 modules, but they're still useful for encapsulation.
Basic IIFE Syntax
// IIFE - the function runs immediately
(function() {
console.log("This runs immediately!");
})();
// Output: This runs immediately!
// IIFE with a different syntax style
!function() {
console.log("Another immediate function");
}();
// IIFE with parameters
(function(name) {
console.log("Hello, " + name);
})("Alice");
// Output: Hello, Alice
// IIFE returning a value
const result = (function() {
return 5 + 3;
})();
console.log(result); // 8
IIFE immediately executes, creating its own scope.
Creating Private Scopes
The main benefit of IIFE is creating a private scope. Variables declared inside an IIFE are not accessible outside.
Private Variables
// Without IIFE - pollutes global scope
var globalVar = "global";
var counter = 0;
// With IIFE - variables are private
(function() {
var privateVar = "private";
let counter = 0;
console.log(privateVar); // "private"
})();
// These are not accessible
// console.log(privateVar); // ReferenceError
// console.log(counter); // 0 (different counter)
// IIFE with multiple variables
(function() {
const name = "Alice";
const age = 25;
const email = "alice@example.com";
console.log(name + " (" + age + "): " + email);
// Output: Alice (25): alice@example.com
})();
// None of these are accessible outside
// Mix private and global
const appName = "MyApp"; // Global
(function() {
const appVersion = "1.0"; // Private
console.log(appName + " v" + appVersion);
// Output: MyApp v1.0
})();
console.log(appName); // "MyApp" - accessible
// console.log(appVersion); // ReferenceError - not accessible
IIFE creates an isolated scope, preventing global namespace pollution.
The Module Pattern
IIFE enables the module pattern, where you create public and private members. This is useful for organizing code.
Module Pattern with IIFE
// Module pattern - public and private members
const Calculator = (function() {
// Private variables
let memory = 0;
// Private function
function validateNumber(num) {
return typeof num === "number";
}
// Public methods (return object with public API)
return {
add: function(x) {
if (validateNumber(x)) {
memory += x;
}
return memory;
},
subtract: function(x) {
if (validateNumber(x)) {
memory -= x;
}
return memory;
},
getMemory: function() {
return memory;
},
reset: function() {
memory = 0;
}
};
})();
// Using the module
console.log(Calculator.add(10)); // 10
console.log(Calculator.add(5)); // 15
console.log(Calculator.subtract(3)); // 12
console.log(Calculator.getMemory()); // 12
Calculator.reset();
console.log(Calculator.getMemory()); // 0
// Private function and variable not accessible
// console.log(Calculator.memory); // undefined
// console.log(Calculator.validateNumber(5)); // undefined
// Practical example: App configuration
const AppConfig = (function() {
// Private configuration
const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
debug: false
};
// Private helper
function parseUrl(url) {
return new URL(url);
}
return {
getApiUrl: function() {
return config.apiUrl;
},
getTimeout: function() {
return config.timeout;
},
setDebug: function(value) {
config.debug = value;
},
isDebug: function() {
return config.debug;
}
};
})();
console.log(AppConfig.getApiUrl());
// https://api.example.com
console.log(AppConfig.getTimeout());
// 5000
Module pattern creates public API while keeping implementation private.
IIFE with Parameters
IIFEs can accept parameters, useful for passing global objects or using strict mode.
IIFE Parameters
// IIFE with global object passed
(function(window, undefined) {
// Safer to reference globals explicitly
console.log(typeof window); // "object"
})(window);
// IIFE with multiple parameters
(function(name, version) {
console.log(name + " v" + version);
})("MyLib", "2.0");
// Output: MyLib v2.0
// IIFE with dependencies
const Module = (function(jQuery, $) {
// Both jQuery and $ are the same
// More explicit about dependencies
return {
doSomething: function() {
// Use jQuery here
}
};
})(jQuery, jQuery);
// Using strict mode in IIFE
(function() {
"use strict";
x = 10; // Error: x is not defined
// Safer than global scope
})();
// Safer global reference pattern
(function(global) {
// global refers to window in browser
// or global in Node.js
global.myGlobal = "I'm global";
})(typeof window !== "undefined" ? window : global);
Parameters make IIFE safer by creating local references to globals.
Modern Alternatives to IIFE
With ES6, modules and block scope are preferred over IIFE, but IIFE is still valid and useful in certain contexts.
IIFE vs Modern Alternatives
// Old way with IIFE
const Counter1 = (function() {
let count = 0;
return {
increment: () => ++count,
get: () => count
};
})();
// Modern way with ES6 module
// counter.js file:
// let count = 0;
// export const increment = () => ++count;
// export const get = () => count;
// When ES6 modules aren't available:
// Use IIFE to prevent global pollution
// Block scope (but no return value)
{
const privateVar = "only in block";
console.log(privateVar);
}
// console.log(privateVar); // ReferenceError
// Both work, but IIFE for encapsulation with return value
// Block scope for simple isolation
ES6 modules are preferred, but IIFE is still useful.
Common Mistakes
- Forgetting the parentheses at the end: IIFE must have () at the end to invoke: (function(){})(); not (function(){})
- Using var in IIFE unnecessarily: Use const/let inside IIFE for better scoping, or use blocks with const/let instead.
- Not using IIFE for module encapsulation: If you need private members, use IIFE module pattern or ES6 modules.
FAQ
What does IIFE stand for?
IIFE stands for Immediately Invoked Function Expression. It's a function that executes immediately after being defined.
Why use IIFE?
IIFE creates a private scope, prevents global namespace pollution, and enables the module pattern for organizing code.
What's the difference between (function(){}()) and (function(){})?
The first one (with ()) at the end immediately invokes the function. The second one just defines it.
Should I still use IIFE in ES6+?
ES6 modules and block scope are preferred, but IIFE is still useful for creating public/private APIs and when modules aren't available.
Related Topics