🟨 JavaScript

Полный справочник: переменные, типы и приведение, функции, объекты, массивы, async/await, event loop, модули, DOM, ошибки и подводные камни.

Шпаргалки · Программирование · #js #javascript #web #node

Запуск и окружение

Где Как
Браузер <script type="module" src="app.js"></script>, консоль DevTools (F12)
Node.js node app.js, node --watch app.js, REPL node
Менеджеры пакетов npm, pnpm, yarn, bun
Среды Node.js, Deno, Bun
Редакторы VS Code, WebStorm

Стандарт языка называется ECMAScript (ES2015, …, ES2025). Новые возможности работают в современных браузерах и Node 20+.

Переменные и области видимости

const PI = 3.14;      // нельзя переприсвоить (но объект внутри можно менять)
let counter = 0;      // блочная область, можно менять
var old = 1;          // функциональная область, всплытие: избегайте
var let const
Область функция блок {} блок {}
Переприсваивание да да нет
Всплытие значение undefined зона «мёртвого времени» (ошибка до объявления) то же
Повторное объявление можно нельзя нельзя

По умолчанию пишите const, let только если значение меняется.

Типы данных

Тип Примеры
number 42, 3.14, NaN, Infinity
bigint 10n, 2n ** 64n
string 'a', "b", `x=${x}`
boolean true, false
null, undefined пусто намеренно / не задано
symbol Symbol('id')
object {}, [], функции, Date, Map
typeof 5;            // 'number'
typeof null;         // 'object' (историческая ошибка)
Array.isArray([]);   // true
Number.isInteger(5); Number.isNaN(NaN); Number.isFinite(1);

Ложные значения (falsy)

false, 0, -0, 0n, '', null, undefined, NaN. Всё остальное истинно, включая '0', [], {}.

Приведение типов

Number('42');   // 42      Number('') // 0     Number('abc') // NaN
parseInt('42px', 10);       // 42
parseFloat('3.14abc');      // 3.14
String(123); (123).toString(); `${123}`;
Boolean('a'); !!value;
'5' + 1;   // '51' (склейка)
'5' - 1;   // 4

Сравнивайте === и !==: == приводит типы (0 == '' истинно, null == undefined истинно).

Операторы

Группа Операторы
Арифметика + - * / % ** ++ --
Сравнение === !== < > <= >=
Логика `&&
Null-безопасность ?? (по умолчанию для null/undefined), ?. (безопасный доступ), ?.(), ?.[]
Присваивание = += -= *= /= **= ??= ||= &&=
Прочее ... (spread / rest), typeof, instanceof, in, delete, void, ,
const city = user?.address?.city ?? 'не указан';
config.timeout ??= 3000;            // присвоить, если null/undefined
a ||= 'x';                           // если a ложно
const [x, y] = [1, 2];  [x, y] = [y, x];     // обмен значениями

Разница ?? и ||: 0 || 5 даёт 5, а 0 ?? 5 даёт 0.

Условия

if (n > 0) {} else if (n === 0) {} else {}
const label = n > 0 ? '+' : '-';
switch (x) { case 1: …; break; case 2: case 3: …; break; default: … }

Циклы

for (let i = 0; i < 3; i++) {}
for (const v of [1, 2, 3]) {}                // значения массивов, строк, Map, Set
for (const k in obj) {}                       // ключи объекта (включая унаследованные)
for (const [k, v] of Object.entries(obj)) {}
while (cond) {}  do {} while (cond);
arr.forEach((v, i) => {});                    // без break; для await не подходит
break;  continue;  outer: for (...) { break outer; }

Функции

function add(a, b = 0) { return a + b; }           // объявление (всплывает)
const mul = (a, b) => a * b;                        // стрелочная: нет своих this и arguments
const sum = (...nums) => nums.reduce((s, n) => s + n, 0);   // rest
add(...[1, 2]);                                     // spread
const curry = (a) => (b) => a + b;                  // замыкание
(() => { /* IIFE */ })();
  • Замыкание: функция помнит переменные места создания.
  • this: у обычной функции зависит от вызова (obj.f() → obj), у стрелочной берётся из окружения. Явно: f.call(obj, a), f.apply(obj, [a]), f.bind(obj).
  • Параметры по значению для примитивов, для объектов копируется ссылка.

Объекты

const user = { name: 'Аня', age: 30, 'full-name': 'x', [key]: 1, greet() { return this.name; } };
user.name; user['full-name']; delete user.age;
const { name, age = 18, ...rest } = user;          // деструктуризация
const copy = { ...user, age: 31 };                  // поверхностная копия
const deep = structuredClone(user);                 // глубокая копия
Метод Что делает
Object.keys / values / entries(o) ключи / значения / пары
Object.fromEntries(pairs) пары в объект
Object.assign(a, b) слить в a
Object.freeze(o) запретить изменения (поверхностно)
Object.hasOwn(o, 'k') свой ключ
JSON.stringify(o) / JSON.parse(s) сериализация

Классы

class User {
  #password;                    // приватное поле
  static count = 0;
  constructor(name, pw) { this.name = name; this.#password = pw; User.count++; }
  get label() { return `@${this.name}`; }
  check(pw) { return pw === this.#password; }
  static create(name) { return new User(name, ''); }
}
class Admin extends User { constructor(n) { super(n, ''); } }
new Admin('root') instanceof User;   // true

Массивы

const a = [3, 1, 2];
a.push(4); a.pop(); a.shift(); a.unshift(0); a.splice(1, 1);   // изменяют массив
a.at(-1); a.slice(1, 3); a.concat([5]); a.includes(2); a.indexOf(2);
a.map(x => x * 2); a.filter(x => x > 1); a.find(x => x > 1); a.findLast(x => x < 3);
a.some(x => x > 2); a.every(x => x > 0);
a.reduce((s, x) => s + x, 0);
a.flat(2); a.flatMap(x => [x, x]);
a.join(', '); Array.from({ length: 3 }, (_, i) => i); Array.of(1, 2);

Сортировка: [...a].sort((x, y) => x - y) (без аргумента сортирует как строки!). Иммутабельные версии (ES2023): toSorted(), toReversed(), toSpliced(), with(i, v). Группировка: Object.groupBy(arr, fn) (современные среды).

Map, Set, WeakMap

const m = new Map([['a', 1]]); m.set('b', 2); m.get('a'); m.has('a'); m.delete('a'); m.size;
for (const [k, v] of m) {}
const s = new Set([1, 1, 2]); s.add(3); s.has(2); [...s];
const unique = [...new Set(arr)];

Map лучше обычного объекта для словарей с произвольными ключами. WeakMap / WeakSet не мешают сборке мусора.

Строки (кратко)

includes, startsWith, endsWith, indexOf, slice, split, trim, padStart, replaceAll, at, repeat, toUpperCase, localeCompare, normalize, matchAll. Подробности в шпаргалке «JS: методы строк».

Числа, даты, Intl

Math.max(...a); Math.min(); Math.round(); Math.floor(); Math.ceil(); Math.trunc(); Math.random(); Math.abs(); Math.pow(2, 3);
(0.1 + 0.2).toFixed(2);              // '0.30' (строка); 0.1 + 0.2 !== 0.3
new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' }).format(1234.5);
new Date().toISOString(); new Date('2026-01-31T10:00:00Z'); Date.now();
new Intl.DateTimeFormat('ru-RU', { dateStyle: 'long' }).format(new Date());

Деньги храните целыми числами в копейках или используйте BigInt / библиотеки.

Итераторы и генераторы

function* ids() { let i = 0; while (true) yield i++; }
const it = ids(); it.next().value;
for await (const chunk of asyncIterable) {}

Асинхронность

JavaScript однопоточный. Event loop: синхронный код → микрозадачи (Promise.then, queueMicrotask) → макрозадачи (setTimeout, события, I/O).

console.log(1); setTimeout(() => console.log(2)); Promise.resolve().then(() => console.log(3)); console.log(4);
// 1 4 3 2
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function load(id, signal) {
  const res = await fetch(`/api/items/${id}`, { signal });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);          // отмена по таймауту
try { const data = await load(1, ctrl.signal); } catch (e) { console.error(e); }
Комбинатор Поведение
Promise.all([...]) все, падает при первой ошибке
Promise.allSettled([...]) результаты всех, без падения
Promise.race([...]) первый завершившийся
Promise.any([...]) первый успешный

Параллельно: await Promise.all(ids.map(load)). Последовательно: цикл for ... of с await внутри. Не используйте await в forEach.

Ошибки

try { JSON.parse(text); } catch (e) { if (e instanceof SyntaxError) {} else throw e; } finally { cleanup(); }
class HttpError extends Error { constructor(status, msg) { super(msg); this.name = 'HttpError'; this.status = status; } }
throw new Error('что-то пошло не так', { cause: err });

Необработанные отклонения: process.on('unhandledRejection', …) (Node), window.addEventListener('unhandledrejection', …).

Модули

// ESM
export const a = 1; export default function f() {}
import f, { a } from './mod.js';  const lazy = await import('./heavy.js');
// CommonJS (Node, старый)
const fs = require('fs'); module.exports = { f };

В Node для ESM: "type": "module" в package.json или расширение .mjs.

Регулярные выражения

/(\d{4})-(\d{2})/.exec('2026-05');          // группы
'a1b2'.replace(/\d/g, '#');                  // 'a#b#'
const { groups } = /(?<y>\d{4})-(?<m>\d{2})/.exec('2026-05');

Флаги: g все, i без регистра, m строки, s точка и перенос, u Unicode, y липкий.

DOM (браузер)

const el = document.querySelector('.card');  document.querySelectorAll('li');
el.textContent = 'текст'; el.innerHTML = '…';          // innerHTML опасен для чужих данных (XSS)
el.classList.add('on'); el.classList.toggle('on'); el.setAttribute('id', 'x'); el.dataset.id;
document.createElement('div'); parent.append(el); el.remove();
el.addEventListener('click', (e) => { e.preventDefault(); }, { once: true });
parent.addEventListener('click', (e) => e.target.closest('button')); // делегирование
localStorage.setItem('k', JSON.stringify(v)); sessionStorage; new URL(location.href).searchParams.get('q');

Подводные камни

  • 0.1 + 0.2 !== 0.3: сравнивайте с допуском.
  • typeof null === 'object', NaN !== NaN (Number.isNaN).
  • sort() по умолчанию лексикографический.
  • parseInt('08') без основания: всегда указывайте 10.
  • Мутация общих объектов при поверхностной копии.
  • this теряется при передаче метода как колбэка: используйте стрелку или bind.
  • Утечки: неснятые слушатели и таймеры.

Библиотеки и инструменты по задачам

Задача Что взять
Сервер Express, Fastify, Hono, NestJS
UI React, Vue, Svelte, Angular, Solid
Сборка Vite, esbuild, Rollup, webpack
HTTP fetch, axios, ky
Даты date-fns, Day.js, Temporal (новый стандарт)
Валидация zod, valibot, Yup
Состояние Redux Toolkit, Zustand, Pinia, TanStack Query
Утилиты lodash-es
Тесты Vitest, Jest, Playwright, Testing Library
Качество кода ESLint, Prettier, TypeScript