Познакомьтесь с iffy в JS (или освежите память за 3 минуты :))

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

Я подготовил для вас несколько примеров, а также распространенные ловушки, с которыми вы можете столкнуться во время собеседования.

Как правильно это сделать

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

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

Примеры

Базовый синтаксис (обратите внимание на круглые скобки)

(function() {
  /* your work here */
  const scopedVariable = "I am available only in this block";
  console.log(`You will see me in the console. ${scopedVariable}`);
})() 
// or with arrow function
(() => {
  /* your work here */
  const scopedVariable = "I am available only in this block";
  console.log(`You will see me in the console. ${scopedVariable}`);
})() 

Мы можем немного изменить синтаксис.
() теперь находится внутри скобок выражения.
Работает так же (просто сохраняйте кодовую базу согласованной).

(function() {
  /* still works */
}())

(() => {
  /* still works */
}())

Мы также можем дать имя нашей функции — и имя функции namedStillScoped не «утекает» в глобальное пространство имен.

(function namedStillScoped() {
  console.log("puma");
})();

Я также видел это в дикой природе:

;(function() {
  /* */
})()

На самом деле это хитрый трюк старой школы, поскольку он предотвращает проблемы при слепом объединении двух вещей.

Поскольку JavaScript не требует точек с запятой, мы (или упаковщик) можем объединить слишком много случайностей. Что-то вроде этого вылетит:

const willCrash = 'Hi there!'(function () {
  // note the lack of semicolon after 'Hi There!'
})();

Поскольку инструменты linting, веб-пакет и т. д., это редко бывает.
Но все же полезно об этом знать.

IIFE может принимать параметры и возвращать значение

Здесь мы используем функцию параметров по умолчанию ES6, а также создаем объект с коротким синтаксисом.

const person = (function (name = "puma", id = 1) {
  return {
    id,
    name,
  }; 
})();
console.log(person);
// { id: 1, name: 'puma' }

IIFE для создания служебной переменной

Мы можем создать объект с помощью методов.

<script src="https://cdnurl.com/somelibrary.js"></script>
<script>
   const myUtility = (function () {
      function createMyUtility() {
         // logic here
      }
      function anotherMyUtilityMethod() {
         // logic here
      }
      return {
         createMyUtility,
         anotherMyUtilityMethod
      }
   })(); 
</script>

Мы можем использовать его так myUtility.createMyUtility().
Это особенно полезно, когда мы создаем некоторые плагины или пакеты, и мы хотим, чтобы имена были ограничены.

Использование асинхронного ожидания

Вы также можете сделать что-то подобное (пример взят из среды Node.js).
Мы не можем использовать await вне async, и тогда IIFE может нам помочь.
Пример, конечно, упрощен, просто чтобы дать вам подсказку, что это вариант.

(async () => {
  try {
    await doSomething();
  } catch (e) {
    console.error(e.stack);
    process.exit(1);
}})();

Пара слов о let и const

ES6 представил нам let и const.

Оба они используют область действия блока.

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

Во многих случаях этого недостаточно, и именно поэтому мы должны знать и понимать IIFE.

Сценарий интервью

Вопрос «расскажите мне о IIFE» до сих пор является очень распространенным вопросом на собеседованиях.
Часто появляется дополнительный вопрос, например, простой фрагмент:

function foo(){ 
 // will I run?
}();

Мы уже знаем, что синтаксис неверен и что он должен быть одним из следующих:

(function foo() {
 // I will run because of the wrapping parenthesis
})()
// or this
(function foo() {
 // I will run too
}())

Другой вопрос, который вы можете получить, — «почему он возвращает значение undefined»:

const foo = void (function bar() {
  return 'foo';
})();

console.log(foo); // undefined

Теперь это ловушка, потому что IIFE будет работать. Тогда почему он возвращает undefined?
Это сводится к ключевому слову void, которое указывает, что функция ничего не возвращает. Если мы удалим ключевое слово void, IIFE будет работать правильно.

TL;DR

IIFE в JavaScript:

  • вызываются сразу после создания
  • отличный способ защитить область видимости (IIFE создает собственную область видимости)
  • синтаксис IIFE (помните об скобках и () в конце для вызова функции
(function() {
  /* */
})()

(() => {
  /* */
})()

Резюме

Как мы видим, IIFE в JavaScript на самом деле простая, но мощная функция.

Его определенно стоит иметь в заднем кармане.