Немедленно вызванное функциональное выражение
( Немедленно вызываемое функциональное выражение или IIFE , произносится как «iffy», IPA /ˈɪf.i/) — это идиома языка программирования , которая создает лексическую область видимости с использованием области видимости функции . Он был популярен в JavaScript [1] как метод поддержки модульного программирования до внедрения более стандартизированных решений, таких как модули CommonJS и ES . [2]
Немедленно вызываемые функциональные выражения можно использовать, чтобы избежать подъема переменных из блоков, защитить от загрязнения глобальной среды и одновременно разрешить публичный доступ к методам, сохраняя при этом конфиденциальность для переменных, определенных внутри функции.
Использование
[ редактировать ]Непосредственно вызываемые функциональные выражения могут быть записаны различными способами. [3] Распространенным соглашением является заключение функционального выражения (и, при необходимости, оператора его вызова) с помощью оператора группировки: [4] в скобках, чтобы явно указать синтаксическому анализатору ожидать выражения. В противном случае в большинстве ситуаций, когда парсер встречает function
ключевое слово, он рассматривает его как объявление функции (оператор), а не как выражение функции. [5] [6]
(function () { /* ... */ })();
(function () { /* ... */ }());
(() => { /* ... */ })(); // With ES6 arrow functions (though parentheses only allowed on outside)
Существуют и другие способы принудительного применения функционального выражения: [ нужна ссылка ]
!function () { /* ... */ }();
~function () { /* ... */ }();
-function () { /* ... */ }();
+function () { /* ... */ }();
void function () { /* ... */ }();
delete function () { /* ... */ }();
typeof function () { /* ... */ }();
await function () { /* ... */ }();
В контекстах, где ожидается выражение, заключение в круглые скобки не требуется:
let f = function () { /* ... */ }();
true && function () { /* ... */ }();
0, function () { /* ... */ }();
Передача переменных в область видимости осуществляется следующим образом:
(function(a, b) { /* ... */ })("hello", "world");
Начальная скобка — это один из случаев, когда автоматическая вставка точки с запятой (ASI) в JavaScript может вызвать проблемы; вместо этого выражение интерпретируется как вызов последнего термина в предыдущей строке. В некоторых стилях, в которых необязательные точки с запятой опущены, точка с запятой ставится перед скобками и называется защитной точкой с запятой . [7] [8] Например:
a = b + c
;(function () {
// code
})();
...чтобы избежать анализа как c()
.
Примеры
[ редактировать ]Ключом к пониманию шаблонов проектирования, таких как IIFE, является осознание того, что до ES6 JavaScript имел только область видимости функции (поэтому отсутствовала область видимости блока ), передавая значения по ссылке внутри замыканий . [9] Это уже не так, поскольку версия JavaScript для ES6 реализует область видимости блоков с использованием нового let
и const
ключевые слова. [10]
Контекст оценки
[ редактировать ]Отсутствие области действия блока означает, что переменные, определенные внутри (например) цикла for, будут иметь свое определение, «поднятое» в начало включающей функции. Вычисление функции, которая зависит от переменных, измененных внешней функцией (в том числе путем итерации), может быть затруднено. Мы можем увидеть это без цикла, если обновим значение между определением и вызовом функции. [11]
let v, getValue;
v = 1;
getValue = function () { return v; };
v = 2;
getValue(); // 2
Хотя результат может показаться очевидным при обновлении v
вручную, это может привести к непредвиденным результатам, если getValue()
определяется внутри цикла.
Далее функция переходит v
в качестве аргумента и вызывается немедленно, сохраняя контекст выполнения внутренней функции. [12]
let v, getValue;
v = 1;
getValue = (function (x) {
return function () { return x; };
})(v);
v = 2;
getValue(); // 1
Это эквивалентно следующему коду:
let v, getValue;
v = 1;
function f(x) {
return function () { return x; };
};
getValue = f(v);
v = 2;
getValue(); // 1
Установка частных переменных и методов доступа
[ редактировать ]IIFE также полезны для создания частных методов для доступных функций, при этом предоставляя некоторые свойства для дальнейшего использования. [13] Следующий пример взят из поста Алмана о IIFE. [1]
// "counter" is a function that returns an object with properties, which in this case are functions.
let counter = (function () {
let i = 0;
return {
get: function () {
return i;
},
set: function (val) {
i = val;
},
increment: function () {
return ++i;
}
};
})();
// These calls access the function properties returned by "counter".
counter.get(); // 0
counter.set(3);
counter.increment(); // 4
counter.increment(); // 5
Если мы попытаемся получить доступ counter.i
из глобального окружения, оно будет неопределенным, поскольку оно заключено в вызываемую функцию и не является свойством counter
. Аналогично, если мы попытаемся получить доступ i
, это приведет к ошибке, поскольку мы не объявили i
в глобальной среде.
Терминология
[ редактировать ]Первоначально известная как «самоисполняющаяся анонимная функция», [14] Бен Алман позже представил нынешний термин IIFE как более семантически точное название идиомы, вскоре после его обсуждения на comp.lang.javascript. [1] [15] [16]
Примечательно, что немедленно вызываемые функции не обязательно должны быть анонимными по своей сути, а строгий режим ECMAScript 5 запрещает arguments.callee
, [17] что делает первоначальный термин неправильным .
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ Jump up to: а б с Алман, Бен (15 ноября 2010 г.). «Немедленно вызываемые функциональные выражения» . Архивировано из оригинала 1 декабря 2017 года . Проверено 18 января 2019 г.
- ^ Макгиннис, Тайлер (15 января 2019 г.). «Модули JavaScript: от IIFE к модулям CommonJS и ES6» . ui.dev . Проверено 18 августа 2021 г.
- ^ Линдли, Коди (2013). Просвещение JavaScript . О'Рейли. п. 61. ИСБН 978-1-4493-4288-3 .
- ^ «Оператор группировки» . Сеть разработчиков Mozilla. 2 октября 2023 г.
- ^ Закас, Николас (2012). Поддерживаемый JavaScript . О'Рейли. п. 44. ИСБН 978-1-4493-2768-2 .
- ^ Аксель Раушмайер. «Изучение JS» .
- ^ «Вставка точки с запятой в JavaScript: все, что вам нужно знать» . 28 мая 2010 г. Архивировано из оригинала 2 октября 2017 г.
- ^ Марохнич, Мислав (7 мая 2010 г.). «Точки с запятой в JavaScript необязательны» . Архивировано из оригинала 8 августа 2017 года.
- ^ Хавербеке, Марин (2011). Красноречивый JavaScript . Нет крахмального пресса. стр. 29–30. ISBN 978-1-59327-282-1 .
- ^ ECMAScript 6: Новые функции: обзор и сравнение, блочные переменные
- ^ Алман, Бен. "simple-iife-example.js" . Гитхаб . Проверено 5 февраля 2013 г.
- ^ Отеро, Сезар; Ларсен, Роб (2012). Профессиональный jQuery . Джон Уайли и сыновья. п. 31. ISBN 978-1-118-22211-9 .
- ^ Реттиг, Паскаль (2012). Профессиональная разработка мобильных игр на HTML5 . Джон Уайли и сыновья. п. 145. ИСБН 978-1-118-30133-3 .
- ^ Резиг, Джон (2006). Профессиональные методы JavaScript . Апресс. стр. 29. ISBN 978-1-4302-0283-7 .
- ^ Османи, Адди (2012). Изучение шаблонов проектирования JavaScript . О'Рейли. п. 206. ИСБН 978-1-4493-3487-1 .
- ^ Баагоэ, Йоханнес. «Закрывающая скобка в определении функции с последующим ее вызовом» . Проверено 19 апреля 2010 г.
- ^ «Строгий режим» . Справочник Mozilla по JavaScript . Сеть разработчиков Mozilla . Проверено 4 февраля 2013 г.
Внешние ссылки
[ редактировать ]- «Функции и область действия функций» . Справочник Mozilla по JavaScript . Сеть разработчиков Mozilla . Проверено 4 февраля 2013 г.