С 2015 года JavaScript обновляется каждый год. На собесе ждут, что вы свободно читаете современный код и знаете, какие задачи решают новые возможности. Здесь всё, что поддерживается во всех актуальных браузерах и в Node.js 22.
Деструктуризация
const { name, age = 18, address: { city } = {} } = user;
const [first, , third, ...rest] = list;
[a, b] = [b, a]; // обмен значений без временной переменной
- Значение по умолчанию срабатывает только для
undefined, не дляnull. - Переименование:
const { name: userName } = user. - Деструктуризация
nullилиundefinedбросает TypeError:const { a } = null. - В параметрах:
function f({ id, title } = {}) {}.
Spread и rest
Три точки означают разное в зависимости от места:
- spread раскрывает:
[...arr, 4],{ ...obj, a: 1 },fn(...args); - rest собирает:
function f(...args),const { a, ...others } = obj.
При spread объектов поздние свойства перезаписывают ранние: { ...defaults, ...options }. Копируются только собственные перечисляемые свойства, геттеры вычисляются и превращаются в значения.
Опциональная цепочка и нулевое слияние
user?.address?.city // undefined, если чего-то нет, без TypeError
user.getName?.() // вызов, только если метод существует
list?.[0] // доступ по индексу
const port = config.port ?? 3000;
?. останавливается при null или undefined и возвращает undefined для всего выражения (короткое замыкание: остаток цепочки не вычисляется).
?? подставляет правую часть только для null и undefined, а || для любого ложного значения. Для чисел и строк, где 0 и '' допустимы, нужен ??. Смешивать ?? с || или && без скобок запрещено синтаксисом.
Логическое присваивание (ES2021)
options.timeout ??= 5000; // присвоить, если null или undefined
cache[key] ||= compute(); // присвоить, если ложно
user.isAdmin &&= check(); // присвоить, если истинно
Присваивание происходит только если нужно: a ||= b не трогает a, если оно истинно, и b при этом не вычисляется.
Шаблонные строки
`Привет, ${name}` поддерживают многострочность и выражения. Теговые шаблоны tag`...` передают строки и значения в функцию: так устроены styled-components, graphql, sql-хелперы.
Map, Set, WeakMap, WeakSet
- Map: ключи любого типа, порядок вставки,
size, быстрые частые добавления и удаления. Объект для этого хуже: ключи только строки и символы, есть унаследованные свойства. - Set: уникальные значения. Убрать дубли:
[...new Set(arr)]. - WeakMap / WeakSet: ключи только объекты (и незарегистрированные символы), не мешают сборке мусора, не итерируются.
Новые методы Set (ES2025, есть в Node 22 и всех браузерах с 2024 года): union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom.
Symbol
Уникальный примитив: Symbol('id') !== Symbol('id'). Используется для ключей, которые не пересекутся с чужими, и для встроенных протоколов: Symbol.iterator, Symbol.toPrimitive, Symbol.asyncIterator. Символьные ключи не видны в Object.keys, for...in и JSON.stringify.
Новые методы массивов и объектов
| Версия | Что |
|---|---|
| ES2019 | flat, flatMap, Object.fromEntries |
| ES2020 | ?., ??, BigInt, Promise.allSettled, globalThis |
| ES2021 | ??=, ` |
| ES2022 | at(), Object.hasOwn, поля и #-члены классов, top-level await, Error.cause |
| ES2023 | findLast, findLastIndex, toSorted, toReversed, toSpliced, with |
| ES2024 | Object.groupBy, Map.groupBy, Promise.withResolvers, Array.fromAsync |
| ES2025 | методы Set, iterator helpers, RegExp модификаторы |
Самое полезное на практике:
arr.at(-1); // последний элемент
const sorted = arr.toSorted((a, b) => a - b); // без мутации
const updated = arr.with(0, 'новое'); // замена по индексу без мутации
const byRole = Object.groupBy(users, (u) => u.role); // { admin: [...], user: [...] }
const { promise, resolve, reject } = Promise.withResolvers();
Object.groupBy возвращает объект без прототипа, у него нет hasOwnProperty. Map.groupBy возвращает Map и подходит, когда ключи объекты.
Частые ошибки
||вместо??для значений, где 0 допустим.- Ждать, что дефолт в деструктуризации сработает для
null. - Думать, что spread делает глубокую копию.
?.в левой части присваивания:a?.b = 1это SyntaxError.
Что спросят на собесе
- Чем
??отличается от||, как работает?.. - Что такое деструктуризация, когда срабатывает значение по умолчанию.
- Чем Map отличается от объекта, Set от массива, WeakMap от Map.
- Какие новые возможности ES2022-ES2024 вы используете.
- Чем spread отличается от rest.