Деструктуризация в JavaScript: объекты и массивы

Содержание

О проверке кода. Примеры не запускались — в отличие от материалов по Node.js с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».

Деструктуризация — из ECMAScript 6, и это одна из тех вещей, после которых старый код читать больно. Разберём, как вынимать данные из объектов и массивов кратко.

Разбор объекта

const user = { name: 'Аня', age: 30, city: 'Москва' };

// без деструктуризации
const name = user.name;
const age = user.age;

// с деструктуризацией — одна строка
const { name, age } = user;

Имена переменных совпадают с именами свойств — JavaScript берёт user.name и кладёт в name. Порядок неважен, важны имена. Свойства, которые не упомянули, просто не берутся.

Разбор массива

const coords = [55.75, 37.61];

const [lat, lng] = coords;   // lat = 55.75, lng = 37.61

// пропустить элемент — оставить пустое место
const [first, , third] = [1, 2, 3];   // first = 1, third = 3

// поменять переменные местами без временной
let a = 1, b = 2;
[a, b] = [b, a];   // a = 2, b = 1

Массив разбирают по позиции, не по имени. Первая переменная — первый элемент, и так далее. Пропущенную позицию оставляют пустой (запятая без имени). Обмен переменных местами [a, b] = [b, a] — классический трюк, который деструктуризация делает элегантным.

Именно так Geolocation API отдаёт координаты, а Object.entries — пары ключ-значение: for (const [key, value] of ...).

Значения по умолчанию

const { role = 'user' } = { name: 'Аня' };   // role = 'user' — свойства не было
const { name = 'гость' } = { name: 'Борис' }; // name = 'Борис' — свойство есть

const [x = 0, y = 0] = [5];   // x = 5, y = 0

Значение по умолчанию подставляется, если свойства нет или оно undefined. Это защищает от undefined при разборе неполных объектов — то же поведение, что у параметров функций по умолчанию.

Переименование

const { name: userName, age: userAge } = user;
// переменные будут userName и userAge, а не name и age

Через двоеточие свойство попадает в переменную с другим именем. Нужно, когда имя свойства конфликтует с уже существующей переменной или когда хочется более говорящее имя. Синтаксис путает новичков: слева от : — имя свойства в объекте, справа — имя новой переменной.

Комбинируется с дефолтами:

const { role: userRole = 'user' } = obj;   // переименовать И задать умолчание

Вложенная деструктуризация

const user = {
  name: 'Аня',
  address: { city: 'Москва', zip: '101000' },
};

const { name, address: { city } } = user;
// name = 'Аня', city = 'Москва'

Можно разбирать вложенные структуры сразу. Но осторожно: address: { city } не создаёт переменную address — только city. Если нужны обе, укажите явно. Глубокая вложенность быстро становится нечитаемой — тогда лучше разобрать в два шага.

Главное применение: параметры функции

Здесь деструктуризация раскрывается полностью:

// ❌ много позиционных аргументов — легко перепутать порядок
function createUser(name, age, city, isAdmin, sendEmail) {}
createUser('Аня', 30, 'Москва', false, true);   // что означает true?

// ✅ объект-настройки с деструктуризацией и дефолтами
function createUser({ name, age, city = 'не указан', isAdmin = false }) {
  // ...
}
createUser({ name: 'Аня', age: 30, city: 'Москва' });   // понятно, что к чему
Позиционные аргументы против объекта-настроек

Позиционные аргументы

Порядок важен и легко перепутать

  • fn(a, b, c, d)
  • Что значит четвёртый true?
  • Пропустить средний нельзя
  • Добавить параметр — сломать порядок

Объект + деструктуризация

Именованные, с дефолтами

  • fn({ name, size = 10 })
  • Порядок неважен, всё по именам
  • Легко пропустить необязательное
  • Новый параметр не ломает вызовы

Как только у функции больше двух-трёх параметров — переходите на объект-настройки. Вызов становится самодокументируемым, порядок перестаёт иметь значение, а добавление нового параметра не ломает существующие вызовы. Этот приём используют React-компоненты (props), опции API и большинство современных библиотек.

Деструктуризация с rest

Собрать «всё остальное» в отдельную переменную:

const { name, ...rest } = { name: 'Аня', age: 30, city: 'Москва' };
// name = 'Аня', rest = { age: 30, city: 'Москва' }

const [head, ...tail] = [1, 2, 3, 4];
// head = 1, tail = [2, 3, 4]

...rest собирает то, что не разобрали явно. Частый приём — вынуть одно свойство, а остальное передать дальше: const { password, ...safe } = user убирает пароль перед отправкой объекта клиенту. Подробнее — про spread и rest.


Смежные темы: spread и rest — три точки подробно; объекты; функции — параметры. Полный список — в уроках JavaScript.

Частые вопросы

Что такое деструктуризация?
Синтаксис, который вынимает значения из объекта или массива в отдельные переменные одной строкой: const { name } = user вместо const name = user.name. Экономит код и делает его читаемее.
Как задать значение по умолчанию при деструктуризации?
Через знак равно: const { role = ‘user’ } = obj. Если свойства нет или оно undefined, подставится значение по умолчанию. Работает и для объектов, и для массивов.
Как переименовать переменную при разборе объекта?
Через двоеточие: const { name: userName } = user. Свойство name попадёт в переменную userName. Полезно, когда имя свойства конфликтует с существующей переменной.
Чем деструктуризация массива отличается от объекта?
Массив разбирают по позиции: const [first, second] = arr. Объект — по имени свойства: const { name } = obj. В массиве важен порядок, в объекте — имена, порядок неважен.
Зачем деструктуризация в параметрах функции?
Чтобы принимать объект-настройки и сразу разбирать его на именованные параметры со значениями по умолчанию: function create({ name, size = 10 }). Читается лучше, чем длинный список позиционных аргументов.