JavaScript: Модули
Пока программа маленькая, весь код можно хранить в одном файле. Такой подход удобен для простых примеров и небольших задач. Но со временем программа начинает расти. Когда кода становится много, ориентироваться в одном файле становится сложно. Реальные приложения состоят из десятков тысяч строк (как минимум) и сотен файлов.
Чтобы разделить программу на отдельные логические части, в JavaScript используют модули. Отдельный файл с кодом и есть модуль. А язык предоставляет механизмы, с помощью которых один файл может использовать функции и константы из другого.
export и import
Модуль сам решает, что отдать наружу. Для этого используют ключевое слово export. Другой файл подключает экспортированное через import.
Скорее всего, такие строки вы уже видели в начале некоторых заданий — теперь разберёмся, что они значат:
import { length } from "hexlet-basics/string";
console.log(length("Hello!")); // => 6Эта строчка подключает функцию length из модуля hexlet-basics/string и делает её доступной в текущем файле.
Именованный импорт
Из одного модуля можно импортировать сразу несколько имён, перечислив их в фигурных скобках:
import { reverse, toUpperCase } from "hexlet-basics/string";
console.log(reverse("hexlet")); // => telxeh
console.log(toUpperCase("hexlet")); // => HEXLETПосле такого импорта к функциям обращаются напрямую, по их именам. Это удобно: не нужно каждый раз писать, из какого модуля взята функция.
Экспорт по умолчанию
Чтобы что-то экспортировать, модуль помечает это словом export. Экспорт бывает двух видов. Именованный — экспортируемых имён может быть сколько угодно:
// string.js
const reverse = (s) => s.split("").reverse().join("");
const length = (s) => s.length;
export { reverse, length };И экспорт по умолчанию — он в модуле может быть только один. С таким экспортом вы уже сталкивались, когда определяли функции:
// sum.js
const sum = (a, b) => a + b;
export default sum;Импорт по умолчанию пишется без фигурных скобок, и имя при импорте можно выбрать любое:
import sum from "./sum.js";
console.log(sum(2, 3)); // => 5Переименование при импорте
Иногда имя из модуля уже занято в текущем файле. Чтобы избежать конфликта, импорт можно переименовать через as:
import { reverse as reverseString } from "hexlet-basics/string";
console.log(reverseString("hexlet")); // => telxehТеперь функция доступна под именем reverseString, а исходное имя reverse остаётся свободным.
Стандартные модули
У каждого языка есть набор готовых функций. В JavaScript бо́льшая часть из них доступна глобально и импорта не требует — например, объект Math для математики или console для вывода.
Но JavaScript исполняется в разных средах. В серверном окружении Node.js есть встроенные модули, которые нужно подключать. Их подключают с префиксом node: — например, модуль node:fs для работы с файлами:
import { readFile } from "node:fs/promises";Готовые функции можно брать не только из стандартных, но и из сторонних модулей. О том, как они распространяются, поговорим в следующем уроке.
Задание
Реализуйте функцию mirror(). Она принимает строку, переворачивает её и переводит в верхний регистр, после чего возвращает результат.
Используйте функции reverse() и toUpperCase() из модуля hexlet-basics/string. Импорт нужно написать самостоятельно.
mirror("hello"); // => 'OLLEH'
mirror("Hexlet"); // => 'TELXEH'Подсказка
- В начале файла импортируйте нужные функции:
import { reverse, toUpperCase } from 'hexlet-basics/string'; - Сначала переверните строку, затем переведите результат в верхний регистр
Полезное
JavaScript: Модули
Пока программа маленькая, весь код можно хранить в одном файле. Такой подход удобен для простых примеров и небольших задач. Но со временем программа начинает расти. Когда кода становится много, ориентироваться в одном файле становится сложно. Реальные приложения состоят из десятков тысяч строк (как минимум) и сотен файлов.
Чтобы разделить программу на отдельные логические части, в JavaScript используют модули. Отдельный файл с кодом и есть модуль. А язык предоставляет механизмы, с помощью которых один файл может использовать функции и константы из другого.
export и import
Модуль сам решает, что отдать наружу. Для этого используют ключевое слово export. Другой файл подключает экспортированное через import.
Скорее всего, такие строки вы уже видели в начале некоторых заданий — теперь разберёмся, что они значат:
import { length } from "hexlet-basics/string";
console.log(length("Hello!")); // => 6Эта строчка подключает функцию length из модуля hexlet-basics/string и делает её доступной в текущем файле.
Именованный импорт
Из одного модуля можно импортировать сразу несколько имён, перечислив их в фигурных скобках:
import { reverse, toUpperCase } from "hexlet-basics/string";
console.log(reverse("hexlet")); // => telxeh
console.log(toUpperCase("hexlet")); // => HEXLETПосле такого импорта к функциям обращаются напрямую, по их именам. Это удобно: не нужно каждый раз писать, из какого модуля взята функция.
Экспорт по умолчанию
Чтобы что-то экспортировать, модуль помечает это словом export. Экспорт бывает двух видов. Именованный — экспортируемых имён может быть сколько угодно:
// string.js
const reverse = (s) => s.split("").reverse().join("");
const length = (s) => s.length;
export { reverse, length };И экспорт по умолчанию — он в модуле может быть только один. С таким экспортом вы уже сталкивались, когда определяли функции:
// sum.js
const sum = (a, b) => a + b;
export default sum;Импорт по умолчанию пишется без фигурных скобок, и имя при импорте можно выбрать любое:
import sum from "./sum.js";
console.log(sum(2, 3)); // => 5Переименование при импорте
Иногда имя из модуля уже занято в текущем файле. Чтобы избежать конфликта, импорт можно переименовать через as:
import { reverse as reverseString } from "hexlet-basics/string";
console.log(reverseString("hexlet")); // => telxehТеперь функция доступна под именем reverseString, а исходное имя reverse остаётся свободным.
Стандартные модули
У каждого языка есть набор готовых функций. В JavaScript бо́льшая часть из них доступна глобально и импорта не требует — например, объект Math для математики или console для вывода.
Но JavaScript исполняется в разных средах. В серверном окружении Node.js есть встроенные модули, которые нужно подключать. Их подключают с префиксом node: — например, модуль node:fs для работы с файлами:
import { readFile } from "node:fs/promises";Готовые функции можно брать не только из стандартных, но и из сторонних модулей. О том, как они распространяются, поговорим в следующем уроке.
Задание
Реализуйте функцию mirror(). Она принимает строку, переворачивает её и переводит в верхний регистр, после чего возвращает результат.
Используйте функции reverse() и toUpperCase() из модуля hexlet-basics/string. Импорт нужно написать самостоятельно.
mirror("hello"); // => 'OLLEH'
mirror("Hexlet"); // => 'TELXEH'Подсказка
- В начале файла импортируйте нужные функции:
import { reverse, toUpperCase } from 'hexlet-basics/string'; - Сначала переверните строку, затем переведите результат в верхний регистр
Полезное
Ваше упражнение проверяется по этим тестам
// @ts-check
import { expect, test } from "vitest";
import mirror from "./index.js";
test("modules", () => {
expect(mirror("hello")).toBe("OLLEH");
expect(mirror("Hexlet")).toBe("TELXEH");
});Решение учителя откроется через:
20:00
