IIFE
IIFE (Immediately Invoked Function Expression) — функциональное выражение, которое вызывается сразу после создания. Создаёт изолированную область видимости.
Зачем нужно
IIFE позволяет создать область видимости, не загрязняя глобальное пространство имён. До появления ES-модулей и блочной области видимости (let/const) это был основной способ инкапсуляции кода в JavaScript.
Где используется
Модульный паттерн (до ES-модулей), инициализация библиотек, изоляция переменных, полифиллы, защита от конфликтов имён, скрипты на страницах.
Предпосылки
Function Expression, Замыкания (Closures), Переменные
Синтаксис
Основные формы
// Классическая форма
(function {
console.log('IIFE выполнена');
});
// Альтернативная форма (скобки вокруг вызова)
(function {
console.log('IIFE выполнена');
});
// Стрелочная функция
(() => {
console.log('Arrow IIFE');
});
// С параметрами
(function(window, document) {
// window и document — локальные алиасы
console.log(window.location.href);
})(window, document);
Именованная IIFE
(function init() {
console.log('Инициализация');
// Имя init доступно для рекурсии внутри, но не снаружи
});
// init; // ReferenceError
Изоляция переменных
// Без IIFE — загрязнение глобальной области
var counter = 0;
var name = 'app';
// Эти переменные могут конфликтовать с другими скриптами
// С IIFE — всё изолировано
(function {
var counter = 0;
var name = 'app';
// Эти переменные не видны снаружи
});
Модульный паттерн
const Calculator = (function {
// Приватное состояние
let history = ;
// Приватная функция
function addToHistory(operation) {
history.push({
operation,
timestamp: Date.now()
});
}
// Публичный API
return {
add(a, b) {
const result = a + b;
addToHistory(`${a} + ${b} = ${result}`);
return result;
},
subtract(a, b) {
const result = a - b;
addToHistory(`${a} - ${b} = ${result}`);
return result;
},
getHistory {
return [...history];
}
};
});
Calculator.add(2, 3); // 5
Calculator.subtract(10, 4); // 6
console.log(Calculator.getHistory);
// history и addToHistory недоступны извне
Расширение модуля
const MyModule = (function(module) {
// Добавляем новый функционал к существующему модулю
module.newFeature = function {
return 'Новая функция';
};
return module;
})(MyModule || {});
Практические примеры
Инициализация приложения
(function {
'use strict';
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000
};
function init() {
setupEventListeners;
loadInitialData;
console.log('Приложение инициализировано');
}
function setupEventListeners() {
document.querySelector('#btn').addEventListener('click', handleClick);
}
function handleClick(event) {
console.log('Клик!');
}
function loadInitialData() {
fetch(config.apiUrl).then(r => r.json()).then(console.log);
}
// Запуск после загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init;
}
});
Защита от конфликтов (jQuery)
// $ может быть перезаписан другой библиотекой
(function($) {
// Здесь $ точно jQuery
$(document).ready(function {
$('.menu').toggle;
});
})(jQuery);
Создание уникального ID-генератора
const generateId = (function {
let id = 0;
return function(prefix = 'id') {
return `${prefix}_${++id}`;
};
});
console.log(generateId); // "id_1"
console.log(generateId('user')); // "user_2"
console.log(generateId); // "id_3"
Однократная инициализация
const database = (function {
console.log('Подключение к БД...');
const connection = { host: 'localhost', port: 5432 };
return {
query(sql) {
console.log(`Запрос: ${sql} на ${connection.host}`);
}
};
}); // Подключение происходит один раз при загрузке
database.query('SELECT * FROM users');
Async IIFE
// Для использования await на верхнем уровне (до top-level await)
(async function {
try {
const response = await fetch('/api/data');
const data = await response.json();
console.log(data);
} catch (err) {
console.error('Ошибка:', err);
}
});
// Стрелочная версия
(async () => {
const data = await fetchData;
processData(data);
});
Современные альтернативы
ES-модули
// module.js — каждый модуль имеет свою область видимости
let counter = 0;
export function increment() { return ++counter; }
export function getCount() { return counter; }
// counter изолирован автоматически
Блочная область видимости
// let/const в блоке — достаточно для изоляции
{
const privateVar = 'скрыто';
let mutableVar = 0;
// ...
}
// privateVar и mutableVar не видны здесь
Когда IIFE всё ещё полезна
| Ситуация | IIFE нужна? |
|---|---|
| Модуль в ES-модульной системе | Нет, используй ESM |
Скрипт в <script> без type=module |
Да |
| Инициализация в глобальном скрипте | Да |
Полифилл / библиотека для <script> |
Да |
| Создание замыкания в одну строку | По ситуации |
Частые ошибки
1. Забытые скобки вокруг функции
// SyntaxError — JS думает, что это Function Declaration
// function { console.log('test'); };
// Правильно — оборачиваем в скобки
(function { console.log('test'); });
2. Отсутствие точки с запятой перед IIFE
const x = 42
// Без ; перед IIFE может быть ошибка
(function {})
// JS может интерпретировать как: 42(function {})
// Решение: ставить ; или начинать IIFE с ;
;(function {})
3. Возврат значения без присваивания
// Результат IIFE потерян
(function {
return { data: 'важные данные' };
});
// Правильно — присвоить результат
const result = (function {
return { data: 'важные данные' };
});
Практика
- Создай IIFE, которая объявляет приватную переменную и возвращает объект для работы с ней
- Реализуй модульный паттерн для корзины покупок (add, remove, getTotal)
- Напиши IIFE с параметрами, принимающую
windowиdocument - Создай async IIFE, которая загружает данные при инициализации
- Перепиши IIFE-модуль на ES-модуль — сравни подходы
Связанные темы
Ресурсы
🎓 Источник: Функции, стрелочные функции, контексты, замыкания
- 📅 2018-09-27 · YouTube · ID:
pn5myCmpV2U - Тезисы:
- IIFE = Immediately Invoked Function Expression
- Объявил → вызвал → забыл ссылку
- Раньше нужно было для изоляции контекста — сейчас достаточно блока
{}сlet/const - До ES6 IIFE использовали в цикле с
var, чтобы зафиксировать значение итератора
- Цитата: «Это было необходимо в JavaScript раньше, когда нельзя было создавать контексты при помощи скобочек.»