Модули

13-10-24 18:30:07


Image for the Модули

Модули стали стандартной функцией JavaScript (ECMAScript) с выпуском ES6 в 2015 году. Система модулей теперь широко поддерживается в современных браузерах и Node.js, что делает её неотъемлемой частью современного JavaScript-разработки.

Что такое модуль?

Модуль — это по сути отдельный файл, который содержит код, такой как функции, классы или переменные, которые могут быть импортированы в другие файлы. Модули JavaScript поддерживают два типа экспорта:

  1. Именованный экспорт: можно экспортировать несколько объектов из модуля.
  2. Экспорт по умолчанию: можно экспортировать один объект в качестве экспорта по умолчанию.

Экспорт в модулях JavaScript

Чтобы сделать код доступным для использования в других модулях, его необходимо экспортировать. Существует два основных способа экспорта элементов из модуля: именованный экспорт и экспорт по умолчанию.

Именованный экспорт

С помощью именованного экспорта можно экспортировать несколько объектов из модуля. Эти объекты должны быть импортированы с такими же именами в импортирующем модуле.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// utils.js
export function greet(name) {
return `Привет, ${name}!`;
}
export const PI = 3.14159;

В приведенном выше примере math.js экспортирует две функции, add и subtract, а utils.js экспортирует функцию greet и константу PI.

Экспорт по умолчанию

При экспорте по умолчанию модуль может экспортировать один элемент, который можно импортировать под любым именем в импортирующем модуле.

// logger.js
export default function logMessage(message) {
console.log(message);
}

В этом примере logger.js экспортирует одну функцию по умолчанию с именем logMessage. При импорте этой функции можно выбрать любое имя для неё.

Импорт в модулях JavaScript

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

Импорт именованных экспортов

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

// main.js
import { add, subtract } from './math.js';
import { greet, PI } from './utils.js';

console.log(add(5, 3)); // Вывод: 8
console.log(subtract(5, 3)); // Вывод: 2
console.log(greet('Алиса')); // Вывод: Привет, Алиса!
console.log(PI); // Вывод: 3.14159

Импорт по умолчанию

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

// app.js
import logMessage from './logger.js';

logMessage('Это пример экспорта по умолчанию.'); // Вывод: Это пример экспорта по умолчанию.

Переименование при экспорте и импорте

Можно переименовать экспорты и импорты, если вы хотите использовать другие имена в импортирующем модуле.

// math.js
export { add as addition, subtract as subtraction };

// main.js
import { addition, subtraction } from './math.js';

console.log(addition(4, 2)); // Вывод: 6
console.log(subtraction(4, 2)); // Вывод: 2

Использование import * as

​Можно импортировать все именованные экспорты из модуля как один объект, что позволяет обращаться к экспортированным элементам как к свойствам этого объекта.

// main.js
import * as MathOperations from './math.js';

console.log(MathOperations.add(10, 5)); // Вывод: 15
console.log(MathOperations.subtract(10, 5)); // Вывод: 5

Динамический импорт

Динамический импорт позволяет загружать модули условно или асинхронно с помощью функции import(). Это полезно для ленивой загрузки, когда модуль загружается только при необходимости, что может улучшить производительность приложения.

// dynamic.js
export function sayHello() {
console.log('Привет из динамически импортированного модуля!');
}

// main.js
if (true) {
import('./dynamic.js').then(module => {
module.sayHello(); // Вывод: Привет из динамически импортированного модуля!
}).catch(err => {
console.error('Не удалось загрузить модуль:', err);
});
}

В этом примере import('./dynamic.js') возвращает промис, который разрешается модулем. Затем можно получить доступ к экспортированной функции или переменной из модуля.

Использование await с динамическим импортом

При работе с async/await также можно использовать динамический импорт для асинхронной загрузки модулей.

// main.js
async function loadAndRun() {
try {
const module = await import('./dynamic.js');
module.sayHello(); // Вывод: Привет из динамически импортированного модуля!
} catch (err) {
console.error('Ошибка загрузки модуля:', err);
}
}

loadAndRun();

Комбинирование статического и динамического импорта

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

// utils.js
export const utilFunction = () => console.log('Функция утилита выполнена.');

// main.js
import { utilFunction } from './utils.js';

utilFunction(); // Вывод: Функция утилита выполнена.

if (true) {
import('./dynamic.js').then(module => {
module.sayHello(); // Вывод: Привет из динамически импортированного модуля!
});
}

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

Экспорт всего из другого модуля

Можно повторно экспортировать все экспорты из одного модуля в другом модуле с помощью export * from 'module'. Это полезно для агрегирования нескольких модулей в один.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// utils.js
export function greet(name) {
return `Привет, ${name}!`;
}
export const PI = 3.14159;

// index.js
export * from './math.js';
export * from './utils.js';

// main.js
import { add, subtract, greet, PI } from './index.js';

console.log(add(10, 5)); // Вывод: 15
console.log(greet('Джон')); // Вывод: Привет, Джон!

Теперь файл index.js служит единым точкой доступа для всех экспортов из math.js и utils.js.