Продвинутый JS: модули
Код растёт — и один файл превращается в хаос. Продвинутый JavaScript — это модули, порядок выполнения асинхронных операций и браузерные хранилища посерьёзнее localStorage.
Модули ESM
ESM — стандартная модульная система: файл объявляет export, другой забирает import. Браузеры уже умеют ES-модули type="module" нативно.
// calc.js
export function sum(a, b) { return a + b; }
export default function hi() { return "Привет!"; }
// main.js
import hi, { sum } from "./calc.js";
console.log(sum(2, 3)); // 5
<script type="module" src="main.js"></script>
<!-- модули загружаются асинхронно; каждая зависимость — отдельный файл -->
Event loop и порядок кода
JS однопоточный, но умеет «подождать». Event loop выстраивает очередь: сначала микрозадачи (промисы), потом задачи (таймеры). Попробуем угадать вывод:
console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// вывод: 1, 4, 3, 2
ℹ️
Команда идет сразу → печать: 1.
setTimeout(0) — очередь задач, промис — очередь микрозадач, которая выполняется раньше. Отсюда 4 → 3 → 2. Этот вопрос любят на собеседованиях.Замыкания
Функция «запоминает» переменные окружения, в котором создана. Удобный счётчик без глобальных переменных:
function counter() {
let n = 0;
return () => ++n;
}
const c = counter();
console.log(c()); // 1
console.log(c()); // 2
// n недоступна снаружи — только внутри замыкания
IndexedDB вместо localStorage
localStorage — мегабайты строк. IndexedDB — полноценная браузерная база для больших данных и объектов, с индексами.
const req = indexedDB.open("shop");
req.onupgradeneeded = () => {
req.result.createObjectStore("cart", { keyPath: "id" });
};
req.onsuccess = () => {
const db = req.result;
const tx = db.transaction("cart", "readwrite");
tx.objectStore("cart").put({ id: 1, qty: 2 });
};
💡
Грубое правило: localStorage — строка до пары МБ (префы, избранное); IndexedDB — большие структуры (каталоги, кэши); сервер — то, что нужно синхронизировать между устройствами.