Возможности ES6+
ES6 (ECMAScript 2015) и следующие ежегодные редакции превратили JavaScript из языка функций и объектов в язык с полноценным синтаксисом распаковки данных, короткими формами безопасного доступа и стандартной системой модулей. Это не сахар ради красоты — за каждой конструкцией стоит конкретная механика: spread делает поверхностную копию, ?? реагирует только на nullish, import даёт живую привязку. Именно эти грани отличают кандидата, который «видел синтаксис», от того, кто понимает, что происходит под капотом.
Тема собирает возможности, которые встречаются в каждом файле современного кода. Ловушки здесь тонкие и повторяющиеся из собеседования в собеседование — разница ?? против ||, spread против rest, необязательный параметр против умолчания. Разберите каждый слой отдельно; полная карта — ниже.
Карта темы
- Деструктуризация — распаковка массивов по позиции и объектов по имени одним выражением, вплоть до вложенности, псевдонимов и обмена переменных.
- Rest и spread — оператор
...собирает остаток в один массив (rest) или раскрывает источник во многие элементы (spread), делая поверхностную копию. - Параметры по умолчанию — запасное значение параметра, срабатывающее строго на
undefinedи вычисляемое лениво на каждый вызов. - for...of и for...in — перебор значений итерируемого объекта против перечислимых ключей любого объекта.
- Опциональная цепочка
?.— безопасный доступ, замыкающийся кundefinedпри nullish-ссылке вместо выброса ошибки. - Оператор нулевого слияния
??— подстановка умолчания только наnull/undefined, в отличие от||, который реагирует на любое ложное значение. - Классы ES6 —
class,constructor,extends/super,staticи приватные#полякак синтаксис над прототипами. - ES-модули —
import/export, приватная область модуля, живые привязки только для чтения и автоматический строгий режим. - Динамический
import()— загрузка модуля в рантайме, возвращающая промис и включающая разделение кода и ленивую загрузку.
Частые ошибки и ловушки
| Ошибка | Последствие | ||||
|---|---|---|---|---|---|
| Считать, что массивная деструктуризация связывает по имени | На деле [a, b] связывает по позиции, а {x, y} — по имени свойства | ||||
Думать, что {x: y} связывает x | Привязкой становится правое имя y; x — лишь источник | ||||
Путать spread (один → многие) и rest (многие → один) | Неверный смысл ... в конкретной позиции | ||||
Считать {...obj} глубоким клоном | Это поверхностная копия — вложенные объекты общие по ссылке | ||||
| Полагать, что умолчание срабатывает на любом ложном значении | Умолчание применяется только при undefined; 0, '', null его подавляют | ||||
Использовать for...in на массиве ради значений | Он даёт строки-ключи и унаследованные свойства, а не элементы | ||||
Путать ?? с ` | ` | ` | заменяет валидный 0 или ''; ??` реагирует только на nullish | ||
Думать, что ?. защищает всю цепочку | Оно защищает только доступ прямо перед собой | ||||
Вызывать class без new | Выбрасывает TypeError — конструктор нельзя вызвать как функцию | ||||
| Считать классы «чистым сахаром» | Их методы неперечислимы, объявление не всплывает, тело всегда строгое | ||||
Ждать от import() модуль напрямую | Он возвращает промис на объект пространства имён |
Значение для собеседований
ES6 спрашивают, чтобы отделить кандидатов, которые механически применяют синтаксис, от тех, кто понимает семантику. Ответ «?? — это как ||, но красивее» проваливает вопрос; правильный ответ называет конкретную грань: «?? реагирует только на null и undefined, поэтому сохраняет валидный 0».
Что обычно проверяют:
- Разницу связывания по позиции и по имени в деструктуризации; идиому обмена
[a, b] = [b, a]. - Направление
...: собирает (rest) или раскрывает (spread), и что копия поверхностная. - Точный триггер умолчания — только
undefined, а не любое ложное значение. - Чем
for...ofотличается отfor...inна массиве. - Разницу
?./??от||и от «любого ложного значения». - Что классы — синтаксис над прототипами, но с отличиями по перечислимости, всплытию и строгому режиму.
- Что даёт живая привязка ESM и почему
import()включает разделение кода.
Типичный неверный ответ: «{...obj} делает глубокую копию, поэтому изменения источника её не затронут». На деле spread копирует лишь собственные перечислимые свойства на один уровень; вложенные объекты остаются общими, и мутация вложенности видна в обеих копиях.