- JavaScript Immediately-invoked Function Expressions (IIFE)
- Why Use Immediately-invoked Function Expressions (IIFE)
- Named IIFE
- IIFE starting with a semicolon (;)
- Free eBook: Git Essentials
- When to Use an IIFE?
- Aliasing Global Variables
- Creating Private Variables and Functions
- Asynchronous Functions in Loops
- Block Scoping with let and const
- Conclusion
- Enough! Show me an IIFE or I am leaving now!
JavaScript Immediately-invoked Function Expressions (IIFE)
Сразу вызываемое выражение функции, которое выполняется, как только оно определено. IIFE можно использовать, чтобы избежать подъема переменных из блоков и не загрязнять глобальный объект.
Следующий синтаксис представляет, как определить выражение функции, вызываемое немедленно:
(функция(){ //… })();
Следующий синтаксис представляет, как определить IIFE с помощью стрелочных функций:
(() => { /* */ })()
Why Use Immediately-invoked Function Expressions (IIFE)
Определите обычную функцию в javascript. Затем движок js добавляет функцию к глобальному объекту.
Следующий пример:
sum function (a, b) {возвращает a + b; }
В веб-браузерах функция sum () представляет собой сумму двух переменных для объекта окна:
console.log (window.sum);
Точно так же, если вы объявляете переменную вне обычной функции, движок js также добавляет переменную к глобальному объекту:
var counter = 10; console.log (window.counter); // 10
В этом синтаксисе часть справа от оператора присваивания (=) является выражением функции. Поскольку функция является выражением, вы можете заключить ее в круглые скобки:
let sum = (function (a, b) {return a + b; });
В этом примере переменная sum называется анонимной функцией, которая складывает два аргумента.
Если вы объявите много глобальных переменных и функций, механизму JavaScript будет выделяться память до тех пор, пока глобальный объект не потеряет область видимости.
В результате сценарий может неэффективно использовать память. Кроме того, наличие глобальных переменных и функций может вызвать конфликты имен.
Следовательно, лучший способ запретить функциям и переменным выделять память глобальному объекту — использовать выражения функций, которые вызываются немедленно.
Также вы можете запустить функцию сразу после ее создания:
let sum = (function (a, b) {return a + b;}) (10, 20); console.log (сумма);
В этом примере переменная sum содержит результат вызова функции.
Следующее выражение называется выражением немедленно вызываемой функции (IIFE), потому что функция создается как выражение и немедленно выполняется:
(функция (a, b) {return a + b;}) (10,20);
Помещая функции и переменные внутри немедленно вызываемого функционального выражения, вы можете избежать их загрязнения глобальным объектом:
(function () {var counter = 0; function sum (a, b) {return a + b;} console.log (sum (10,20)); // 30 }());
Named IIFE
IIFE может иметь имя. Однако его нельзя вызвать снова после выполнения:
(функция с именемIIFE() { //… })();
IIFE starting with a semicolon (;)
Иногда вы можете увидеть IIFE, начинающийся с точки с запятой(;):</p>; (функция() { /* */ })();
В этом синтаксисе точка с запятой используется для завершения оператора в случае, если два или более файла JavaScript слепо объединены в один файл.
Например, у вас может быть два файла my1.js и my2.js, которые используют IIFE:
(функция () {//…}) () (функция(){ //… })()
Если вы используете инструмент пакета кода для объединения кода из обоих файлов в один файл, без точки с запятой (;) объединенный код JavaScript вызовет синтаксическую ошибку.
Free eBook: Git Essentials
Ознакомьтесь с нашим практическим руководством по изучению Git с лучшими практиками, общепринятыми стандартами и включенной шпаргалкой. Остановите команды Google для Git и изучите их по-настоящему!
Поскольку этот унарный синтаксис менее распространен и может сбивать с толку разработчиков, он обычно не рекомендуется.
IIFE также могут принимать функциональные аргументы. Мы можем передать переменные в области видимости, как показано ниже:
(function (arg1, arg2) {// Код, который выполняется в вашей функции}) («привет», «мир»);
Теперь, когда мы увидели, как создавать IIFE, давайте посмотрим на типичные ситуации, в которых они используются.
When to Use an IIFE?
Наиболее распространенные варианты использования IIFE:
- Псевдонимы глобальных переменных
- Создание частных переменных и функций
- Циклические асинхронные функции
Aliasing Global Variables
Если у вас есть две библиотеки, экспортирующие объект с тем же именем, вы можете использовать IIFE, чтобы убедиться, что они не конфликтуют в вашем коде. Например, библиотеки jQuery и Cash JavaScript экспортируют $ как главный объект.
Вы можете заключить свой код в IIFE, который передает одну из глобальных переменных в качестве аргумента. Допустим, мы хотим убедиться, что $ относится к объекту jQuery, а не к денежной альтернативе. Вы можете убедиться, что jQuery используется со следующим IIFE:
(function ($) {// Код, который выполняется в вашей функции}) (jQuery);
Creating Private Variables and Functions
Мы можем использовать IIFE для создания частных переменных и функций в глобальной области видимости или любой другой области видимости функции.
Функции и переменные, добавленные в глобальную область видимости, доступны для всех скриптов, загруженных на страницу. Предположим, у нас есть функция generateMagicNumber (), которая возвращает случайное число от 900 до 1000 включительно, а также переменную favouriteNumber в нашем файле JavaScript.
Мы можем написать их так:
functiongenerateMagicNumber () {returnMath.floor (Math.random () * 100) + 900; } console.log («Это ваше магическое число:» + generateMagicNumber ()); var избранное число = 5; console.log («Дважды твое любимое число» + favouriteNumber * 2);
Если мы загружаем другие файлы JavaScript в наш браузер, они тоже получают доступ к функциям generateMagicNumber () и favouriteNumber. Чтобы предотвратить их использование или изменение, мы заключаем наш код в IIFE:
(function () {functiongenerateMagicNumber () {returnMath.floor (Math.random () * 100) + 900;} console.log («Это ваше магическое число:» + generateMagicNumber ()); var favavourNumber = 5; журнал консоли («Дважды ваше любимое число» + favouriteNumber * 2); })();
Он работает так же, но теперь generateMagicNumber () и favouriteNumber доступны только в нашем скрипте.
Asynchronous Functions in Loops
Поведение JavaScript многих удивляет, когда обратные вызовы выполняются в цикле. Например, мы считаем от 1 до 5 в JavaScript, вставляя интервал в 1 секунду каждый раз, когда мы регистрируем сообщение. Наивная реализация была бы такой:
for (var i = 1; i <= 5; i ++) {setTimeout (function () {console.log («Я достиг шага» + i);}, 1000 * i); }
Если вы запустите этот код, вы получите следующий результат:
$ node naiveCallbackInLoop.js Я достиг шага 6 Я достиг шага 6 Я достиг шага 6 Я достиг шага 6 Я достиг шага 6
В то время как выходные данные будут печататься 1 секунду за другой, в каждой строке будет указано, что достигнут шаг 6. Почему?
Когда JavaScript обнаруживает асинхронный код, он откладывает выполнение обратного вызова до завершения асинхронной задачи. Вот как он остается неблокирующим. В этом примере оператор console.log () будет выполнен только по истечении тайм-аута.
JavaScript также создал закрытие для нашего обратного вызова. Замыкания — это комбинация функции и ее объема во время создания. С замыканиями наш обратный вызов может получить доступ к переменной i, даже если цикл for уже завершился.
Однако наш обратный вызов имеет доступ только к значению i во время его выполнения. Поскольку весь код внутри функции setTimeout () был отложен, цикл for завершился с i, равным 6. Вот почему все регистрируют, что они достигли шага 6.
Эту проблему можно решить с помощью IIFE:
for (var i = 1; i <= 5; i ++) {(function (step) {setTimeout (function () {console.log (‘Я достиг шага’ + step);}, 1000 * i);}) (i); }
Используя IIFE, мы создаем новую область видимости для нашей функции обратного вызова. Наш параметр шагов IIFE. Каждый раз, когда вызывается наш IIFE, мы передаем ему текущее значение i в качестве аргумента. Теперь, когда обратный вызов готов к выполнению, его закрытие будет иметь правильное значение шага.
Если мы запустим этот фрагмент кода, мы увидим следующий результат:
$ node iifeCallbackInLoop.js Я достиг шага 1 Я достиг шага 2 Я достиг шага 3 Я достиг шага 4 Я достиг шага 5
Хотя IIFE решает нашу проблему с минимальными изменениями кода, давайте посмотрим, как функции ES6 могут упростить выполнение асинхронного кода в циклах.
Block Scoping with let and const
ES6 добавил ключевые слова let и const для создания переменных в JavaScript. Переменные, объявленные с помощью let или const, находятся в области действия блока. Это означает, что к ним можно получить доступ только в пределах ограничивающего блока — области, заключенной в фигурные скобки { }.
Мы считаем от 1 до 5 с интервалом в 1 секунду, используя ключевое слово let вместо var:
for (let i = 1; i <= 5; i ++) {setTimeout (function () {console.log («Я достиг шага» + i);}, 1000 * i); }
Когда мы запустим этот код, мы получим следующий результат:
$ node es6CallbackInLoop.js Я достиг шага 1 Я достиг шага 2 Я достиг шага 3 Я достиг шага 4 Я достиг шага 5
Теперь, когда переменная i находится в области действия блока, замыкания для нашей функции обратного вызова получают соответствующее значение i при окончательном выполнении. Это более кратко, чем наша реализация IIFE.
Использование let — предпочтительный способ выполнения асинхронных функций в цикле,
Conclusion
Выражение немедленно вызываемой функции (IIFE) — это функция, которая выполняется сразу после определения. Этот шаблон использовался для создания псевдонимов глобальных переменных, создания частных переменных и функций, а также для обеспечения правильного выполнения асинхронного кода в циклах.
Несмотря на популярность, мы видели, как изменения в ES6 могут устранить необходимость использования IIFE в современном JavaScript. Однако освоение этой модели также дает нам более глубокое понимание области видимости и замыкания и будет особенно полезно для поддержки устаревшего кода JavaScript.
javascript # node #
Enough! Show me an IIFE or I am leaving now!
Спасибо за терпение и терпение — самый важный навык, необходимый для освоения JavaScript!
Теперь, когда вы освоили определения функций и выражения функций, давайте погрузимся в секретный мир IIFE. Они бывают в некоторых стилистических вариациях. Давайте сначала рассмотрим вариант, который действительно очень легко понять.
Это мои друзья, это наш дорогой IIFE в действии! Когда вы скопируете этот код и попробуете в консоли браузера, вы увидите предупреждение из кода в строке 2. И это почти все. Никто больше никогда не увидит это предупреждение.
Эта функция умерла вскоре после того, как ожила.
Теперь мы понимаем этот не очень интуитивный синтаксис: я знаю, что вы заметили, что «!» в строке 1; Если бы вы этого не сделали, не волнуйтесь, вы бы заметили сейчас!
- Как мы видели ранее, оператор функции всегда начинается с ключевого слова function. Каждый раз, когда JavaScript видит ключевое слово функции как первое слово в допустимом операторе, он ожидает, что будет выполнено определение функции. Итак, чтобы этого не произошло, мы вставляем префикс «!» перед ключевым словом function в строке 1. Это в основном заставляет JavaScript обрабатывать все, что находится после «!» как выражение.
- Но самое интересное происходит в строке 3, где мы немедленно выполняем это функциональное выражение.
Итак, у нас есть выражение функции, которое вызывается сразу после его создания. И это, друзья мои, называется IIFE, независимо от стилистической вариации, используемой для достижения этого эффекта.
Вышеупомянутый стилистический вариант можно использовать, заменив «!» также с «+», «-» или даже «~». В принципе можно использовать любой унарный оператор.
Теперь попробуйте в консоли! И играйте с IIFE в свое удовольствие!
Все, что делает первый символ «!», — это превращение этой функции в выражение, а не в оператор / определение функции. И тогда мы немедленно выполняем эту функцию.
Еще один быстрый вариант этого показан ниже:
Опять же, void в основном заставляет функцию обрабатывать как выражение.
Все вышеперечисленные шаблоны полезны, когда нас не интересует значение, возвращаемое IIIF.
Но что тогда, если вы хотите получить возвращаемое значение из IIIF и хотите использовать это возвращаемое значение в другом месте? Читайте ответ!