IIFE: немедленно вызываемые функции в JavaScript

В этом руководстве вы узнаете о 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. В функции внутри вместо этого используется аргумент _.

Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript