Почему пора перестать использовать JavaScript IIFE

в 9:00, , рубрики: javascript, Блог компании RUVDS.com, Веб-разработка, Программирование, Разработка веб-сайтов

Немедленно вызываемая функция (Immediately Invoked Function Expression — IIFE) в JavaScript — это конструкция, позволяющая вызывать функцию непосредственно после ее определения.

image

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

Мы можем объявлять переменные внутри автономных блоков

С тех пор как появился стандарт ES6, мы можем объявлять переменные и константы внутри блока с помощью let и const. Вместе с этим стандартом также появилась возможность выделять переменные и константы в автономные блоки, недоступные извне.

Например:

{
 let x = 1;
}

Тогда x не будет доступен извне. Это явно лучше, чем:

(()=>{
 let x = 1;
})();

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

Мы можем избавиться почти от всех замыканий

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

Например, здесь мы можем получить некоторые побочные эффекты:

const id = (() => {
 let count = 0;
 return () => {
   ++count;
   return `id_${count}`;
 };
})();

Опять же, теперь нет смысла городить весь этот огород, поскольку у нас есть автономные блоки и модули для изоляции данных. Мы можем просто поместить все это в свой собственный модуль, тогда нам не нужно будет беспокоиться о доступе к данным.

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

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

let count = 0;
export const id = () => {
 ++this.count;
 return `id_${count}`
}

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

Мы можем по-другому создавать алиасы для переменных

Мы могли бы написать такое:

window.$ = function foo() {
 // ...
};(function($) {
 // ...
})(jQuery);

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

И тогда достаточно написать:

import { $ as jQuery } from "jquery";
const $ = () => {};

Кроме того, не стоит добавлять объекту window новые свойства, так как это загрязняет глобальную область видимости.

Мы можем легко получить глобальный объект

С появлением globalThis нам не нужно беспокоиться об имени глобального объекта в различных окружениях, поскольку он становится стандартом.

Мы могли бы использовать IIFE для захвата глобального объекта:

(function(global) {
 // ...
})(this);

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

const globalObj = self || window || global;

Если быть более точным, то можно написать вот что:

const getGlobal = () => {
 if (typeof self !== 'undefined') { return self; }
 if (typeof window !== 'undefined') { return window; }
 if (typeof global !== 'undefined') { return global; }
 throw new Error('unable to locate global object');
};

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

Мы можем проще выполнять минификацию

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

Webpack, Browserify, Parcel, Rollup и так далее могут работать с модулями должным образом, поэтому мы должны использовать их для создания более чистого кода.

Вывод

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

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

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

Автор: ruvds

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js