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

от автора

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

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

ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/494868/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *