Описание тега iife
IIFE расшифровывается как выражение немедленного вызова функции. Он используется в основном для описания шаблона в JavaScript, где выражение функции выполняется сразу после его определения. IIFE обычно имеют следующий синтаксис в JavaScript:
(function() { /* code */ })();
Но есть несколько других допустимых способов формирования IIFE, упомянутых в этом ответе, например
(function() { /* code */ }());
new function(){ /* code */ }();
Термин IIFE был впервые предложен Беном Альманом в этой статье, в которой он предлагает произношение "сомнительный". Он предложил этот термин в качестве альтернативы тому, что он называет "популярным, но вводящим в заблуждение термином самоисполняющаяся анонимная функция".
Наиболее распространенные обозначения, используемые сегодня: (function(){}());
, с вызывающими круглыми скобками внутри группировки ()
, а также (function(){})();
, с вызывающими скобками вне группы.
Помимо незначительной семантической разницы между ними (первый оценивается как (returnvalue of IIFE)
, а второй оценивается как (defined function)<=(call)
) они оба одинаково верны, хотя известный эксперт по JavaScript Дуглас Крокфорд считает вторую нотацию "неправильной" и "нелогичной":
Когда функция должна быть вызвана немедленно, все выражение вызова должно быть заключено в скобки, чтобы было ясно, что создаваемое значение является результатом функции, а не самой функцией.
Из соглашений о коде для языка программирования JavaScript.
Термин IIFE был быстро принят сообществом после его первого появления в конце 2010 года. Просто потому, что это наиболее точное описание самого шаблона:
- II (немедленно вызывается): функция определяется и вызывается за один раз. Это довольно ясно
- F (Функция) Это функция...
- E (выражение): Не просто какая-то старая функция: это скорее выражение, чем утверждение. Это очень важно.
Разница между определением функции и выражением функции заключается в том, где функция определяется (например, придерживаясь JavaScript).
// Any old function:
function f(arg)
{
return arg;
}
Это определение функции будет поднято наверх своей области видимости и станет доступным во всей этой области:
console.log(f(123));
function f(n)
{
return (typeof n);
}
аккуратно войдет number
, хотя кажется, что функция вызывается до ее определения.
Превращая функцию в выражение, определение нельзя поднять:
console.log(typeof f);
var f = function()
{
return 'something';
};
console.log(typeof f);
В этом примере единственное, что будет поднято, - это объявление переменной f
. Само определение функции является выражением в форме правого операнда присваивания. Назначения никогда не поднимаются, поэтому код будет регистрироватьundefined
, а потом function
.
Чтобы превратить это Функциональное выражение в IIFE, мы должны сделать две вещи: Убедитесь, что определение функции является выражением, а не инструкцией. Как объяснялось выше, это достигается за счет включения функции в группировку()
оператор или добавление логического или побитового оператора к оператору, void
префикс или new
ключевое слово.
Заметки:
Используя void
префикс эффективно подавляет возвращаемое значение IIFE и всегда возвращаетundefined
:
var foo = void function()
{
console.log('called');
return 'returnVal';
};
console.log(foo);
Журналы called
, а затем значение foo
-> undefined
.
Используя new
ключевое слово повлияет на контекст вызова (this
ссылка) IIFE_: IIFE будет вести себя как конструктор, возвращая новый объект:
new function()
{
return this.constructor;
};
вернет ссылку на только что вызванную функцию.
Конкретные варианты использования:
- IFFE часто используются при передаче функции в качестве аргумента другой функции (особенно для решения печально известной проблемы цикла)
- Пользовательские конструкторы часто заключаются в оболочку IIFE, что позволяет использовать псевдо (частные) статические свойства. Переменные, объявленные в области видимости IIFE, остаются в памяти до тех пор, пока где-то имеется ссылка на возвращаемое значение этого IIFE. Это возвращаемое значение может быть объектом с функцией, которая, в свою очередь, ссылается на переменные из области IIFE. Вот вам пример.
- В некоторых браузерах, в частности, в более старых версиях InternetExplorer, присоединение обработчиков событий непосредственно к ссылкам DOM вызывало утечки памяти из-за того, что InternetExplorer управлял памятью для DOM и его механизма JScript отдельно. Единственный способ обойти это - присоединить слушателей к IIFE. Когда сценарий завершается, GC (сборщик мусора) может помечать и перемещать всю область IIFE, и вместе с ней все ссылки на DOM и обработчики событий освобождаются.
- Для некоторых шаблонов, таких как шаблон модуля, требуется IIFE. В этой функции модуль создается и в конечном итоге отображается (путем присвоения глобальной переменной) или возвращается.
- Иногда весь скрипт оборачивается IIFE, чтобы избежать глобальных переменных. Это, однако, считается быстрым и незамысловатым решением.