Давайте напишем более защищенный код с IIFE

Вы знали концепцию IIFE, верно?

Проще говоря, из ее полного имени, Immediately Invoked Function Expression, это функция, которая запускается, как только она определена.

IIEF хорошо известны тем, что защищают область переменных. Но что это на самом деле означает? И каковы практические примеры использования МИЭФ?

Вы узнаете ответы в этой статье. Давайте погрузимся в это.

Закрытие

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

Однако вам, вероятно, иногда потребуется изменить значения этих переменных. Является ли это возможным? Да, это так.

Вот как:

Вы ведь знаете, что такое закрытие? Замыкания дают вам возможность получить доступ к области внешней функции из внутренней функции. Создание замыкания - это не что иное, как определение функции внутри другой функции и ее раскрытие.

Комбинируя укупорку с IIFE, вы получаете два больших преимущества.

Во-первых, ограничиваются диапазоны переменных, чтобы предотвратить непредвиденное поведение.

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

const user = (function() {
  let name = ‘anonymous’;
  return {
    getName: _ => name,
    setName: newName => name = newName
  };
})();
console.log(user.getName()) // anonymous
user.setName(‘Amy’);
console.log(user.getName()); // Amy

Переменная name является частной, что означает, что мы можем получить к ней доступ только внутри user IIFE. Однако, поскольку здесь мы используем замыкание, мы можем изменить его извне, открыв метод setName().

Псевдоним глобальных переменных

Использование многих библиотек JavaScript может вызвать конфликты, поскольку некоторые из них могут экспортировать объект с тем же именем.

Допустим, вы используете jQuery. Все мы знаем, что он экспортирует $ в качестве основного объекта. Итак, если в ваших зависимостях есть какая-либо библиотека, использующая $ в качестве экспортируемого объекта, возникнет конфликт.

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

(function ($) {
  // You’re safe to use jQuery here
})(jQuery);

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

Область безопасных переменных

ES6 ввел let и const для более безопасного определения переменных. Использование var может привести к неожиданному результату, потому что его область действия уязвима.

Но что, если производственная среда еще не поддерживает ES6? Или как-то не получается использовать let и const?

Не волнуйся. У вас все еще есть IIFE, выражение немедленного вызова функции, служащее той же цели.

(function () {
  var greeting = ‘Good morning! How are you today?’;
  console.log(greeting); // Good morning! How are you today?
})();
console.log(greeting); // error: Uncaught ReferenceError: greeting is not defined

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

Индекс петли

Выполнение асинхронных задач внутри цикла может привести к неожиданному результату.

Возьмем, например, setTimeout():

for (var i = 0; i < 3; i++) {
  setTimeout(_ => console.log(`We’re at ${i}`), 100);
}

Ожидаете, что результат должен быть:

We’re at 0
We’re at 1
We’re at 2

Но на самом деле это:

We’re at 3
We’re at 3
We’re at 3

Почему? Потому что вызовы console.log() в примере будут выполняться только после каждого 100ms. Цикл может завершиться раньше этого времени, что означает, что индекс i фактически достиг 3. В результате все console.log() напечатают окончательный результат i, 3.

Мы можем решить эту проблему, поместив вызов setTimeout() в IIFE:

for (var i = 0; i < 3; i++) {
  (function(index) {
    setTimeout(_ => console.log(`We’re at ${index}`), 100);
  })(i);
}

Теперь результат правильный:

We’re at 0
We’re at 1
We’re at 2

Однако это возраст ES6, мы можем использовать ключевое слово let, чтобы упростить код:

for (let i = 0; i < 3; i++) {
  setTimeout(_ => console.log(`We’re at ${i}`), 100);
}

Последняя мысль

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

Хотя вы можете заменить некоторые варианты использования IIFE функциями ES6, вам все же следует изучить IIFE, чтобы четко понимать, как область видимости работает в JavaScript. Кроме того, вы не можете сразу адаптировать устаревшие проекты к ES6. Итак, IIFE по-прежнему играют большую роль.

Надеюсь, вам понравится эта статья.

Дальнейшее чтение