Перейти к основному содержимому

[Hard] 📄 IIFE

1. Что такое IIFE?

IIFE расшифровывается как Immediately Invoked Function Expression (немедленно вызываемое функциональное выражение). В отличие от обычного объявления функции, оно оборачивает функцию дополнительными () и немедленно выполняет:

(() => {
console.log(1);
})();

# или

(function () {
console.log(2);
})();

Оно также может выполняться повторно через рекурсию до достижения условия остановки, а завершающие () могут передавать параметры.

(function myIIFE() {
num += 1;
console.log(num);
return num < 5 ? myIIFE(num) : console.log('finished!!');
})((num = 0));

Обратите внимание, что IIFE выполняется во время инициализации (или через внутренние самовызовы), но не может быть вызвано повторно напрямую извне.

2. Зачем использовать IIFE?

Область видимости (Scope)

Поскольку переменные, объявленные внутри функции, имеют область видимости этой функции, IIFE может изолировать состояние и избежать загрязнения глобальной области:

// глобальная область
const name = 'Yumi';
const Hello = () => {
return `Hello ${name}!`;
};

(() => {
const name = 'Pitt';
const Hello = () => {
return `Hello ${name}!`;
};
console.log(name); // результат Pitt
console.log(Hello()); // результат Hello Pitt!
})();

console.log(name); // результат Yumi
console.log(Hello()); // результат Hello Yumi!

Приватные переменные и методы (Private Variables and Methods)

Используя IIFE в сочетании с замыканием (closure), можно создавать приватные переменные и методы. Это означает, что состояние может сохраняться внутри функции и обновляться при каждом вызове (например, увеличение/уменьшение).

const increment = (() => {
let result = 0;
console.log(result);
const credits = (num) => {
console.log(`I have ${num} credits.`);
};
return () => {
result += 1;
credits(result);
};
})();

increment(); // I have 1 credits.
increment(); // I have 2 credits.

Будьте осторожны: поскольку эти переменные сохраняются, чрезмерное использование может потреблять память и снижать производительность.

Модульный паттерн (Module)

Можно предоставить функциональность в форме объекта как модульный паттерн. В примере ниже можно увеличивать значение, а также сбрасывать состояние:

const Score = (() => {
let result = 0;

return {
current: () => {
return result;
},

increment: () => {
result += 1;
},

reset: () => {
result = 0;
},
};
})();

Score.increment();
console.log(Score.current()); // результат 1 => 0 + 1 = 1
Score.increment();
console.log(Score.current()); // результат 2 => 1 + 1 = 2
Score.reset();
console.log(Score.current()); // результат 0 => reset = 0

Другой стиль:

const Score = (() => {
let result = 0;
const current = () => {
return result;
};

const increment = () => {
result += 1;
};

const reset = () => {
result = 0;
};

return {
current: current,
increment: increment,
reset: reset,
};
})();

Score.increment();
console.log(Score.current());
Score.increment();
console.log(Score.current());
Score.reset();
console.log(Score.current());

Ещё одно замечание: поскольку IIFE выполняются немедленно, размещение двух IIFE подряд может нарушить ASI (Automatic Semicolon Insertion — автоматическая вставка точки с запятой). При цепочке IIFE добавляйте точки с запятой явно.