В этом руководстве вы узнаете о JavaScript-функциях с немедленным вызовом (IIFE).
Выражение функции JavaScript, вызываемое немедленно, — это функция, определенная как выражение и выполняемая сразу после создания. Ниже показан синтаксис определения немедленно вызываемого функционального выражения:
(function() { //... })();
Почему IIFE
Когда вы определяете функцию, механизм JavaScript добавляет функцию к глобальному объекту. Следующий пример:
function add(a,b) { return a + b; }
В веб-браузерах механизм JavaScript добавляет функцию add()
к глобальному объекту window
:
console.log(window.add);
Аналогичным образом, если вы объявляете переменную вне функции с помощью ключевого слова var
, движок JavaScript также добавляет переменную в глобальный объект:
var counter = 10; console.log(window.counter); // 10
Если у вас много глобальных переменных и функций, движок JavaScript освободит только память, выделенную для них, до тех пор, пока глобальный объект не потеряет свои области видимости.
В результате скрипт может неэффективно использовать память. Кроме того, наличие глобальных переменных и функций, скорее всего, вызовет конфликты имен.
Один из способов предотвратить загрязнение глобального объекта функциями и переменными — использовать немедленно вызываемые функциональные выражения.
В JavaScript у вас могут быть следующие выражения:
'This is a string'; (10+20);
Этот синтаксис правильный, даже если выражения не имеют никакого эффекта. Функция также может быть объявлена как выражение, которое называется функциональным выражением:
let sum = function(a, b) { return a + b; }
В этом синтаксисе часть справа от оператора присваивания( =
) является функциональным выражением. Поскольку функция является выражением, вы можете заключить ее в круглые скобки:
let sum =(function(a, b) { return a + b; });
В этом примере на переменную sum
ссылаются как на анонимную функцию, которая добавляет два аргумента.
Кроме того, вы можете выполнить функцию сразу после ее создания:
let sum = (function(a, b) { return a + b; })(10, 20); console.log(sum);
В этом примере переменная sum
содержит результат вызова функции.
Следующее выражение называется немедленно вызываемым функциональным выражением(IIFE), поскольку функция создается как выражение и выполняется немедленно:
(function(a, b) { return a + b; })(10, 20);
Это общий синтаксис для определения IIFE:
(function() { //... })();
Обратите внимание, что вы можете использовать функцию стрелки для определения IIFE:
(() = > { //... })();
Помещая функции и переменные внутри немедленно вызываемого функционального выражения, вы можете избежать их загрязнения в глобальном объекте:
(function() { var counter = 0; function add(a, b) { return a + b; } console.log(add(10, 20)); // 30 } ());
Именованное выражение
IIFE может иметь имя. Однако его нельзя вызвать снова после выполнения:
(function namedIIFE() { //... })();
Начинающееся с точки с запятой(;)
Иногда вы можете увидеть IIFE, который начинается с точки с запятой(;):
;(function() { /* */ })();
В этом синтаксисе точка с запятой используется для завершения инструкции в случае, если два или более файла JavaScript слепо объединены в один файл.
Например, у вас может быть два файла lib1.js
и lib2.js
, которые используют IIFE:
(function() { // ... })()(function() { // ... })()
Если вы используете инструмент для объединения кода из обоих файлов в один файл без точки с запятой ( ;
), объединенный код JavaScript вызовет синтаксическую ошибку.
Функция в действии
Предположим, у вас есть библиотека с именем calculate.js со следующими функциями:
function add(a, b) { return a + b; } function mutiply(a, b) { return a * b; }
И вы загружаете calculator.js
в HTML-документ.
Позже вы также захотите загрузить в тот же документ другую библиотеку JavaScript с именем app.js
:
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>JavaScript IIFE</title> </head> <body> <script src="calculator.js"></script> <script src="app.js"></script> </body> </html>
В app.js
также есть функция add()
:
function add() { return 'add'; }
Когда вы используете функцию add()
в документе HTML, она возвращает строку 'add'
вместо суммы двух чисел:
let result = add(10, 20); console.log(result); // 'add'
Это связано с тем, что функция add()
в app.js
переопределяет функцию add()
в библиотеке calculator.js
.
Чтобы исправить это, вы можете применить IIFE в calculate.js следующим образом:
const calculator = (function() { function add(a, b) { return a + b; } function multiply(a, b) { return a * b; } return { add: add, multiply: multiply } })();
IIFE возвращает объект, содержащий методы add
и multiply
, которые ссылаются на функции add()
и multiply()
. В документе HTML вы можете использовать библиотеку calculator.js
следующим образом:
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>JavaScript IIFE</title> </head> <body> <script src="js/calculator.js"></script> <script src="js/app.js"></script> <script> let result = calculator.add(10, 20); // add in app.js console.log(result); // 30 console.log(add()); // add in the app.js </script> </body> </html>
calculator.add()
вызывает функцию add()
, экспортированную с помощью calculator.js
, а второй вызов функции add()
ссылается на функцию add()
в app.js
jQuery и IIFE
В следующем HTML-документе используется библиотека jQuery:
<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>JavaScript IIFE - jQuery</title> </head> <body> <h1>jQuery Demo</h1> <script src="https://code.jquery.com/jquery-3.4.1.slim.js" integrity="sha256-BTlTdQO9/fascB1drekrDVkaKd9PkwBymMlHOiG+qLI=" crossorigin="anonymous"></script> <script> let counter = 1; $('h1').click(function () { $(this).text('jQuery Demo' + ' Clicked ' + counter++); }); </script> </body> </html>
Когда вы импортируете библиотеку jQuery, вы можете получить доступ ко многим полезным функциям jQuery через объект $
или jQuery
. Под капотом jQuery использует IIFE для раскрытия своей функциональности.
Делая это, jQuery просто нужно использовать одну глобальную переменную( $
), чтобы предоставить массу функций, не загрязняя глобальный объект.
В следующем примере показано, как изменить объект jQuery $ на _ внутри IIFE:
(function (_) { let counter = 1; _('h1').click(function () { _(this).text('jQuery Demo' + ' Clicked ' + counter++); }); })(jQuery);
В этом примере мы передали объект jQuery во IIFE. В функции внутри вместо этого используется аргумент _
.