13-10-24 18:30:07
Модули стали стандартной функцией JavaScript (ECMAScript) с выпуском ES6 в 2015 году. Система модулей теперь широко поддерживается в современных браузерах и Node.js, что делает её неотъемлемой частью современного JavaScript-разработки.
Модуль — это по сути отдельный файл, который содержит код, такой как функции, классы или переменные, которые могут быть импортированы в другие файлы. Модули 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. При импорте этой функции можно выбрать любое имя для неё.
Чтобы использовать код из другого модуля, его нужно импортировать с помощью ключевого слова 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') возвращает промис, который разрешается модулем. Затем можно получить доступ к экспортированной функции или переменной из модуля.
При работе с 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.