Self-invoking functions (IIFE — Immediately Invoked Function Expression) are functions that execute immediately after their declaration. They create an isolated scope and don’t pollute the global namespace.
Main advantages:
Self-invoking functions (IIFE) are a pattern in JavaScript where a function is declared and immediately executed. This allows creating an isolated scope.
// Regular function
function sayHello() {
console.log("Hello!");
}
sayHello(); // Need to call separately
// Self-invoking function
(function() {
console.log("Hello!");
})(); // Executes immediately
(function() {
console.log("Executes immediately!");
})();
(function() {
console.log("Also works!");
}());
(function(name, age) {
console.log(`Hello, ${name}! You are ${age} years old.`);
})("Alexander", 30);
(() => {
console.log("IIFE with arrow function!");
})();
// With parameters
((name) => {
console.log(`Hello, ${name}!`);
})("Maria");
const result = (function(a, b) {
return a + b;
})(5, 3);
console.log(result); // 8
// ❌ Problem — variables in global scope
var userName = "Alexander";
var userAge = 30;
function showUser() {
console.log(userName, userAge);
}
// ✅ Solution — isolation with IIFE
(function() {
var userName = "Alexander";
var userAge = 30;
function showUser() {
console.log(userName, userAge);
}
showUser(); // Works only inside IIFE
})();
// console.log(userName); // ReferenceError
// Library A
(function() {
var utils = {
format: function(text) {
return text.toUpperCase();
}
};
// Use utils only here
})();
// Library B
(function() {
var utils = {
format: function(text) {
return text.toLowerCase();
}
};
// Own utils, no conflicts
})();
(function() {
// Setup on page load
const config = {
apiUrl: "https://api.example.com",
timeout: 5000
};
function initApp() {
console.log("Application started!");
console.log("API URL:", config.apiUrl);
}
// Run immediately
initApp();
})();
const Calculator = (function() {
// Private variables
let result = 0;
// Private functions
function log(operation, value) {
console.log(`${operation}: ${value}`);
}
// Public API
return {
add: function(num) {
result += num;
log("Addition", result);
return this;
},
multiply: function(num) {
result *= num;
log("Multiplication", result);
return this;
},
getResult: function() {
return result;
},
reset: function() {
result = 0;
log("Reset", result);
return this;
}
};
})();
// Usage
Calculator.add(5).multiply(2).add(3);
console.log(Calculator.getResult()); // 13
const counter = (function() {
let count = 0;
return {
increment: function() {
count++;
return count;
},
decrement: function() {
count--;
return count;
},
getValue: function() {
return count;
}
};
})();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getValue()); // 2
// console.log(count); // ReferenceError — count is not accessible
const AppConfig = (function() {
const settings = {
theme: "dark",
language: "en",
apiUrl: "https://api.example.com"
};
return {
get: function(key) {
return settings[key];
},
set: function(key, value) {
if (settings.hasOwnProperty(key)) {
settings[key] = value;
}
},
getAll: function() {
return { ...settings }; // Copy, not original
}
};
})();
// Usage
console.log(AppConfig.get("theme")); // "dark"
AppConfig.set("theme", "light");
console.log(AppConfig.get("theme")); // "light"
var x = 10;
(function() {
var x = 20;
console.log(x);
})();
console.log(x);
const module = (function(initial) {
let value = initial;
return {
getValue: () => value,
setValue: (newValue) => { value = newValue; }
};
})(100);
module.setValue(200);
console.log(module.getValue());
console.log(value);
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
// Fix with IIFE
for (var i = 0; i < 3; i++) {
(function(index) {
setTimeout(function() {
console.log(index);
}, 100);
})(i);
}
Will output: 0, 1, 2
// Instead of IIFE for modules
// module.js
let count = 0;
export function increment() {
return ++count;
}
export function getCount() {
return count;
}
// main.js
import { increment, getCount } from './module.js';
// Instead of IIFE for isolation
{
let userName = "Alexander";
const userAge = 30;
console.log(userName, userAge);
}
// console.log(userName); // ReferenceError
// For asynchronous code
(async function() {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
})();
// 1. Creating modules (before ES6)
const MyModule = (function() {
// private code
return { /* public API */ };
})();
// 2. Initialization on load
(function() {
document.addEventListener('DOMContentLoaded', function() {
console.log('Page loaded!');
});
})();
// 3. Library isolation
(function($, window, document) {
// Plugin code
})(jQuery, window, document);
// 4. Configuration
const Config = (function() {
const settings = { /* settings */ };
return { /* access methods */ };
})();
// ❌ Simple calculations
(function() {
return 2 + 2;
})(); // Better just: 2 + 2
// ❌ Modern modules
// Use ES6 import/export
// ❌ Block scope
// Use let/const in blocks {}
// ❌ Error — function is not called
function() {
console.log("Doesn't work!");
};
// ✅ Correct
(function() {
console.log("Works!");
})();
// ❌ Syntax error
(function() {
console.log("Hello!");
}); // Forgot to call
// ✅ Correct
(function() {
console.log("Hello!");
})(); // Call immediately
const obj = {
name: "Alexander",
init: function() {
// ❌ Losing this in IIFE
(function() {
console.log(this.name); // undefined
})();
// ✅ Preserving this
const self = this;
(function() {
console.log(self.name); // "Alexander"
})();
// ✅ Arrow function
(() => {
console.log(this.name); // "Alexander"
})();
}
};
Self-invoking functions (IIFE) are an important JavaScript pattern that:
Advantages:
Application:
Syntax:
(function() {
// code
})();
// or
(() => {
// code
})();
Understanding IIFE will help you write clean and modular code without polluting the global namespace!
Want more interview preparation articles? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪