Понимание функций наизнанку, а затем изучение того, как использовать их для написания современного чистого кода JavaScript, является критически важным навыком для того, чтобы стать ниндзя JavaScript.

Один из часто используемых шаблонов кодирования с функциями получил замысловатое название: Выражение функции с немедленным вызовом или более известное как IIFE и произносится как «сомнительный»

Прежде чем мы сможем понять, что такое IIFE и зачем он нам нужен, нам нужно быстро рассмотреть несколько фундаментальных концепций, касающихся функций JavaScript.

Определение естественной функции

Разработчикам, плохо знакомым с JavaScript, естественно, удобнее использовать следующий синтаксис при работе с функциями.

  1. Строки 1–3 определяют функцию с именем sayHi.
  2. В строке 5 мы вызываем его с обычным синтаксисом «()» для вызова функции.

Этот способ создания функции называется «определением функции», или «объявлением функции», или «оператором функции». Обычно у разработчиков, плохо знакомых с JavaScript, не возникает проблем с использованием этого синтаксиса, поскольку он очень похож на функции / методы других популярных языков программирования.

Эти определения функций всегда начинаются с ключевого слова function и всегда сопровождаются именем функции. Вы не можете пропустить имя, так как оно имеет недопустимый синтаксис.

Функциональные выражения

Именно тогда в JavaScript все становится интереснее. Давайте посмотрим, как выглядит выражение функции.

Этот, казалось бы, простой пример может помочь вам вывести свои навыки JavaScript на новый уровень.

  1. Строка 1 объявляет переменную msg и присваивает ей значение string.
  2. Строки 2–4 объявляют переменную sayHi и присваивают ей значение типа function.
  3. Строка 6 вызывает эту функцию sayHi.

Строку 1 легко понять. Но когда разработчики впервые видят строки 2–4, это обычно противоречит их ожиданиям, если они исходят из других языков программирования, таких как Java.

По сути, в строках 2–4 мы присвоили значение типа function переменной с именем sayHi.

В приведенном выше примере функция в правой части оператора присваивания часто называется «функциональным выражением». Они везде в JavaScript. Большинство написанных вами обратных вызовов часто являются функциональными выражениями.

Возможно, вы использовали эти функциональные выражения, не понимая их основ. Но их освоение даст вам некоторые секретные сверхспособности JavaScript.

Поэтому важно помнить, что функции почти такие же, как и любые другие значения в JavaScript. Они могут быть справа от оператора присваивания или передаваться в качестве аргументов другим функциям.

Выражения анонимной функции

Что ж, вы уже знаете, что это такое. Вышеупомянутый пример был выражением анонимной функции. Они анонимны, потому что у них нет имени после ключевого слова function.

Именованные выражения функций

Выражения функций могут иметь имена. Наиболее утомительное и универсально объяснимое использование этих именованных функциональных выражений связано с рекурсией. Не беспокойтесь об этом сейчас, поскольку вы можете освоить IIFE, не понимая выражений именованных функций.

Таким образом, разница в том, что выражение функции имеет имя «fibonacci», которое можно использовать внутри этого выражения функции для рекурсивного вызова самого себя. (Есть еще кое-что, например, имя функции отображается в трассировке стека и т. Д., Но давайте не будем о них беспокоиться в этом руководстве.)

Достаточно! Покажите мне IIFE, или я ухожу сейчас же!

Спасибо за терпение и терпение - самый важный навык, необходимый для освоения JavaScript!

Теперь, когда вы изучили определения функций и выражения функций, давайте погрузимся в секретный мир IIFE. Они бывают нескольких стилистических вариаций. Давайте сначала рассмотрим вариант, который действительно очень легко понять.

Друзья мои, это наш дорогой IIFE в действии! Когда вы скопируете этот код и попробуете в консоли браузера, вы увидите предупреждение из кода в строке 2. И это почти все. Никто никогда не сможет заставить это предупреждение появиться снова.

Эта функция умерла сразу после того, как ожила.

Теперь давайте разберемся с этим не очень интуитивным синтаксисом: я знаю, что вы заметили этот «!» в строке 1; Если бы вы этого не сделали, не беспокойтесь, вы бы заметили это сейчас!

  1. Как мы видели ранее, оператор функции всегда начинается с ключевого слова function. Каждый раз, когда JavaScript видит ключевое слово function как первое слово в допустимом операторе, он ожидает, что произойдет определение функции. Чтобы этого не произошло, мы добавляем префикс «!» перед ключевым словом function в строке. 1. Это в основном заставляет JavaScript обрабатывать все, что идет после «!», как выражение.
  2. Но самое интересное происходит в строке 3, где мы немедленно выполняем это функциональное выражение.

Итак, у нас есть выражение функции, которое вызывается сразу после создания. И это, друзья мои, называется IIFE, независимо от стилистической вариации, используемой для достижения этого эффекта.

Вышеупомянутый стилистический вариант можно использовать, заменив «!» на «+», «-», или даже «~». В принципе можно использовать любой унарный оператор.

Теперь попробуйте в консоли! И поиграйте с IIFE к своему удовольствию!

Все, что делает здесь первый символ «, - это превращает эту функцию в выражение, а не в оператор / определение функции. И затем мы немедленно выполняем эту функцию.

Еще один быстрый вариант этого показан ниже:

Опять же, void в основном заставляет функцию обрабатывать как выражение.

Все вышеперечисленные шаблоны полезны, когда нас не интересует значение, возвращаемое IIFE.

Но что тогда, если вы хотите получить возвращаемое значение от IIFE и хотите использовать это возвращаемое значение в другом месте? Читайте дальше, чтобы узнать ответ!

Классический стиль IIFE

Паттерн IIFE, который мы видели выше, легко понять. Так что я начал сначала с этого стиля, а не с другого, более традиционного и широко используемого стиля.

Как мы видели в приведенных выше примерах IIFE, ключ к паттерну IIFE - это взять функцию, превратить ее в выражение и немедленно выполнить.

Во-первых, давайте посмотрим еще на один способ сделать выражение функции!

В приведенном выше коде выражение функции заключено в круглые скобки в строках 1–3. Это еще не IIFE, поскольку это выражение функции никогда не выполняется. Теперь, чтобы преобразовать этот код в IIFE, у нас есть два стилистических варианта:

Теперь у нас в действии два IIFE. Может быть, действительно сложно заметить разницу между Вариантом 1 и Вариантом 2. Позвольте мне объяснить это.

  1. В Варианте 1 в строке 4 круглые скобки () для вызова выражения функции содержатся внутри внешних скобок. Снова внешние круглые скобки необходимы, чтобы сделать функциональное выражение из этой функции.
  2. В Варианте 2 в строке 9 круглые скобки () для вызова выражения функции находятся за пределами круглых скобок для выражения функции.

Оба варианта широко используются. Лично я предпочитаю Вариант 1. Если мы перейдем к деталям, то оба варианта немного отличаются в том, как они работают. Но для всех практических целей и краткости этого и без того длинного руководства я скажу, что вы можете использовать любой из них по своему вкусу. (Я сделаю ссылку на будущую статью, которую планирую написать об операторе () и операторе запятая, в котором проясняются нюансы между этими двумя стилями.)

Давайте еще раз проделаем это сквозь стену, увидев пример, который работает, и два примера, которые не работают. С этого момента мы начнем называть наши IIFE, поскольку использование анонимных функций обычно никогда не бывает хорошей идеей.

Теперь вы знаете, почему эти странные круглые скобки вокруг выражения функции необходимы для формирования шаблона IIFE.

Запомни это! Вам нужно выражение функции для формирования IIFE. Операторы / определения функций никогда не используются для создания IIFE.

IIFE и частные переменные

Одна вещь, в которой IIFE действительно хороши, - это их способность создавать область видимости функций для IIFE.

Любые переменные, объявленные внутри IIFE, не видны внешнему миру.

Давайте посмотрим на пример.

В этом примере мы объявили две переменные внутри IIFE, и они являются частными для этого IIFE. Никто за пределами IIFE не имеет к ним доступа. Точно так же у нас есть функция init, к которой никто не имеет доступа за пределами IIFE. Но функция init может получить доступ к этим частным переменным.

В следующий раз, когда вы будете создавать кучу переменных и функций в глобальной области видимости, которые никто не использует вне вашего кода, просто оберните все это в IIFE и получите для этого много хорошей JavaScript-кармы. Ваш код будет продолжать работать, но теперь вы не загрязняете глобальную область видимости. Также вы защищаете свой код от кого-то, кто может случайно, а иногда и намеренно изменить ваши глобальные данные!

Когда мы увидим шаблон модуля, я объясню, как предоставить привилегированный и контролируемый доступ к этим частным переменным миру за пределами IIFE. Так что читайте дальше, чтобы знать это, даже если вы уже чувствуете себя ниндзя IIFE!

IIFE с возвращаемым значением

Если вам не нужно возвращаемое значение из IIFE, вы всегда можете использовать первый стилистический вариант IIFE, который мы видели с унарными операторами, такими как !, +, void и т. д.

Но еще одна действительно важная и мощная особенность IIFE заключается в том, что они могут возвращать значение, которое может быть присвоено переменной.

  1. В этом варианте у нас есть IIFE, у которого есть оператор return в строке 2.
  2. Когда мы выполняем приведенный выше код, в строке 5 отображается предупреждение с возвращаемым значением из IIFE.

В основном IIFE выполняется, конечно же, немедленно, а затем возвращаемое значение присваивается переменной result.

Это действительно мощный шаблон, который мы собираемся использовать при рассмотрении примера шаблона модуля.

IIFE с параметрами

Не только IIFE могут возвращать значения, но IIFE также могут принимать аргументы во время их вызова. Давайте посмотрим на быстрый пример.

  1. В приведенном выше примере в строке 1 IIFE имеет два формальных параметра с именами msg, times соответственно.
  2. Когда мы выполняем IIFE в строке 5, вместо пустых скобок (), которые мы видели до сих пор, мы теперь передаем аргументы IIFE.
  3. Строки 2 и 3 используют эти параметры внутри IIFE.

Это действительно мощный паттерн, и мы часто видим это в коде jQuery, а также в других библиотеках.

В приведенном выше примере мы передаем jQuery, window и document как аргументы IIFE в строке 3. Код внутри IIFE может ссылаться на них как на $, global, document соответственно.

Вот несколько преимуществ их передачи в IIFE.

  1. JavaScript всегда выполняет поиск в области видимости текущей функции и продолжает поиск в более высоких областях, пока не найдет идентификатор. Когда мы передаем документ в строке 3, это единственный раз, когда мы выполняем поиск области вне локальной области для документа . Любые ссылки в IIFE на документ никогда не нужно искать за пределами локальной области действия IIFE. То же самое относится и к jQuery. Прирост производительности от этого может быть незначительным в зависимости от того, насколько тривиален или сложен код IIFE, но все же это полезный трюк, который нужно знать.
  2. Кроме того, минификаторы JavaScript могут безопасно минимизировать имена параметров, объявленные в функции. Если мы не передали их в качестве параметров, минификаторы не уменьшают прямые ссылки на документ или jQuery, поскольку они выходят за рамки этой функции.

Классический шаблон модуля JavaScript

Теперь, когда вы освоили IIFE, давайте посмотрим на пример шаблона модуля, который помещает IIFE и замыкания на стероиды.

Мы реализуем классический одноэлементный объект Sequence, который работает без проблем, и никто не сможет случайно повредить текущее значение последовательности.

Мы напишем этот код в два этапа, чтобы понимать, что происходит постепенно.

  1. В приведенном выше примере у нас есть IIFE, который возвращает объект. См. Строки 7 и 8.
  2. У нас также есть локальная переменная в IIFE с именем current.
  3. Возвращаемое значение IIFE, которое в этом примере является объектом, присваивается переменной Sequence. Строка 12 правильно предупреждает «объект», поскольку мы возвращаем объект из IIFE.

Теперь давайте улучшим это, добавив несколько функций к возвращаемому объекту.

  1. В этом примере мы добавляем две функции к объекту, который мы возвращаем из IIFE.
  2. Строки 8–10 добавляют функцию getCurrentValue, которая возвращает значение в переменной current.
  3. Строки 12–15 добавляют функцию getNextValue, которая увеличивает значение в current на 1, а затем возвращает значение в текущий.

Поскольку переменная current является частной для IIFE, никто, кроме функций, которые имеют к ней доступ через закрытие, не может изменять или получать доступ к current переменная.

(Если вы хотите освоить замыкания, прочтите мой удивительный и популярный учебник по замыканиям: Изучение замыканий JavaScript с помощью законов кармы.)

Это действительно мощный шаблон JavaScript, который вы усвоили. Он сочетает в себе мощь как IIFE, так и закрытий.

Это очень простой вариант шаблона модуля. Есть и другие шаблоны, но почти все они используют IIFE для создания закрытой области видимости.

Когда можно опустить круглые скобки

Скобки вокруг выражения функции в основном заставляют функцию становиться выражением, а не оператором.

Но когда для движка JavaScript очевидно, что это выражение функции, нам технически не нужны окружающие скобки, как показано ниже.

В приведенном выше примере ключевое слово function не является первым словом в инструкции. Таким образом, JavaScript не рассматривает это как оператор / определение функции. Точно так же есть и другие места, где вы можете опустить скобки, если знаете, что это выражение.

Но даже в этом случае я всегда предпочитаю использовать круглые скобки. Использование круглых скобок улучшает читаемость, стилистически намекая читателю в первой строке, что функция будет IIFE. Им не нужно прокручивать до последней строки функции, чтобы понять, что то, что они только что прочитали, в конце концов, было IIFE!

Это все, что нужно знать о IIFE, чтобы начать использовать их в своем коде. Они не только помогают лучше организовать и выразить ваш код, но и помогают уменьшить количество ошибок, избегая создания ненужных глобальных переменных. Теперь вы сертифицированный ниндзя IIFE!

Мне нравится писать эти уроки по JavaScript. Писать их - это так весело. Но они требуют много времени и усилий, чтобы отполировать и опубликовать. Если вы нашли это руководство полезным, вы можете хлопнуть, чтобы выразить свою признательность и помочь порекомендовать его другим. Пожалуйста, подпишитесь на меня здесь, на Medium, а также в Twitter, чтобы получать обновления всякий раз, когда публикуется новая статья.

Если у вас есть какие-либо мысли и идеи по поводу этого урока, вы всегда можете оставить отзыв ниже. Если вы хотите, чтобы я писал на какие-либо другие темы, также оставьте сообщение.

Это было много JavaScript, сделайте глубокий вдох и отдохните от JavaScript, прочитав мой последний пост.



Другие мои руководства по JavaScript здесь: