Skip to main content

Деструктуризація в JavaScript

Destructuring assignment (деструктуризація): синтаксис JavaScript, який витягує значення з масивів або властивості об'єктів в окремі змінні за один крок, замість кількох рядків ручного присвоєння.

Теорія

TL;DR

  • Уяви що розпаковуєш посилку з підписаними комірками: береш тільки потрібне і кладеш в підписані кошики
  • Деструктуризація масивів працює за позицією, а об'єктів, за назвою ключа
  • Значення за замовчуванням спрацьовує тільки коли значення undefined, не null чи 0
  • Rest (...) збирає решту елементів і завжди має стояти останнім
  • Використовуй коли витягуєш 2+ значення; для одного значення точкова нотація читабельніша

Швидкий приклад

javascript
// Масив: за позицією const [first, second] = [10, 20, 30]; console.log(first); // 10 console.log(second); // 20 // Об'єкт: за назвою ключа const user = { name: 'Alice', age: 25 }; const { name, age } = user; console.log(name); // 'Alice' console.log(age); // 25

Двигун читає зліва направо: для масивів використовує індекси, для об'єктів шукає властивість через GetOwnProperty. Скомпільований код еквівалентний ручному присвоєнню, тому різниці у продуктивності немає.

Коли використовувати

  • API-відповіді з кількома полями: const { data, error } = await fetchUser(id)
  • Параметри функції з об'єкта: function greet({ name, role = 'user' }) {}
  • Обмін змінними: [a, b] = [b, a] без тимчасової змінної
  • React hooks: const [count, setCount] = useState(0)
  • Іменовані імпорти: import { useState, useEffect } from 'react'

Для одного значення краще пропусти. user.name читабельніше ніж const { name } = user, якщо тобі потрібне тільки воно.

Патерни для масивів

Пропуск елементів через порожній слот:

javascript
const [first, , third] = [1, 2, 3]; console.log(third); // 3

Rest збирає решту:

javascript
const [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4]

Значення за замовчуванням спрацьовує тільки при undefined:

javascript
const [x = 5] = [0]; console.log(x); // 0 (не 5, бо 0 не є undefined)

Патерни для об'єктів

Перейменування через двокрапку після ключа:

javascript
const { name: userName } = { name: 'Alice' }; console.log(userName); // 'Alice'

Вкладені патерни потребують вкладеного синтаксису:

javascript
const { address: { city } } = { address: { city: 'Kyiv' } }; console.log(city); // 'Kyiv'

Якщо address є undefined, це кине TypeError. Додай значення за замовчуванням або перевір через optional chaining (?.) перед деструктуризацією.

Rest для об'єктів збирає всі залишкові ключі:

javascript
const { id, ...rest } = { id: 1, name: 'Alice', age: 25 }; console.log(rest); // { name: 'Alice', age: 25 }

Типові помилки

Вкладена деструктуризація кидає TypeError на undefined.

javascript
const data = {}; const { user: { name } } = data; // TypeError: Cannot read properties of undefined

Виправлення: const { user: { name } = {} } = data або data.user?.name.

Rest не може стояти не в кінці.

javascript
const [...rest, last] = [1, 2, 3]; // SyntaxError

Rest має бути останнім. [first, ...rest] працює, [...rest, last] не скомпілюється.

Неправильна назва ключа при перейменуванні.

javascript
const { userName } = { name: 'Alice' }; console.log(userName); // undefined

userName шукає ключ буквально з назвою userName. Для перейменування потрібен синтаксис { name: userName }.

Значення за замовчуванням не замінює null.

javascript
const [x = 5] = [null]; console.log(x); // null (замовчування спрацьовує тільки для undefined)

Де зустрічається в реальних проектах

  • React: const [value, setValue] = useState(''), пропси компонента function Button({ onClick, label })
  • Express/Node.js: const { id } = req.params, const { page = 1 } = req.query
  • Redux Toolkit: const { type, payload: { id } } = action
  • SWR/React Query: const { data, error } = useSWR('/api/user')

Питання на співбесіді

Q: Що виведе const [x = 1] = [0]?
A: 0. Значення за замовчуванням спрацьовує тільки коли значення undefined. Нуль є визначеним значенням.

Q: Що станеться якщо деструктурувати ключ якого немає в об'єкті?
A: Отримаєш undefined. Помилки не буде, якщо тільки не спробуєш деструктурувати властивість цього undefined.

Q: Як по-різному поводяться null і undefined зі значеннями за замовчуванням?
A: Тільки undefined активує значення за замовчуванням. null проходить як є. Це часте джерело помилок на співбесідах.

Q: Можна деструктурувати повернуте значення функції?
A: Так. const [success, data] = await fetchData() працює коли функція повертає масив.

Q: (Senior) Як V8 компілює const { x } = obj?
A: Емітує перевірку GetOwnProperty для ключа x на obj, потім присвоює результат новій прив'язці. Патерни масивів компілюються до індексованого доступу (arr[0], arr[1]). Rest використовує перебір властивостей або slice. Байткод еквівалентний ручному присвоєнню.

Приклади

Базовий: масиви та об'єкти

javascript
const coords = [10, 20, 30]; const [x, y] = coords; console.log(x, y); // 10 20 const product = { title: 'Keyboard', price: 99, stock: 5 }; const { title, price } = product; console.log(title, price); // 'Keyboard' 99

Деструктуризація масиву бере за індексом, об'єкта за ключем. Якщо ключ не існує, отримаєш undefined, а не помилку.

Реальний сценарій: параметри функції з замовчуваннями

javascript
// Форма очікуваного вводу видна прямо в сигнатурі function handleRequest({ params: { id }, query: { role = 'viewer', page = 1 } }) { console.log(id, role, page); } handleRequest({ params: { id: '42' }, query: { role: 'admin' } }); // '42', 'admin', 1

Такий патерн зустрічається в React-компонентах, Express-хендлерах і Redux-редюсерах. На практиці це найкорисніше застосування деструктуризації: бачиш що функція очікує не заходячи в тіло. Це скорочує час на розуміння незнайомого коду.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?