Об'єкти — частина 2
JavaScript destructuring — розпаковка подарунка з окремо загорнутими частинами всередині
У минулому уроці ми вивчили основи об'єктів. Тепер розберемо сучасні способи роботи з ними — деструктуризацію, spread оператор та optional chaining. Ці інструменти використовуються в кожному сучасному JavaScript та React проєкті.
Destructuring — деструктуризація об'єктів
Замість витягувати властивості по одній, можна "розпакувати" їх одразу:
const user = { name: "Олексій", age: 25, city: "Київ" };
// Без деструктуризації
const name = user.name;
const age = user.age;
// З деструктуризацією
const { name, age, city } = user;
console.log(name); // "Олексій"
console.log(age); // 25
console.log(city); // "Київ"
Перейменування
const user = { name: "Олексій", age: 25 };
const { name: userName, age: userAge } = user;
console.log(userName); // "Олексій"
console.log(userAge); // 25
Значення за замовчуванням
const user = { name: "Олексій" };
const { name, age = 0, role = "user" } = user;
console.log(age); // 0 (значення за замовчуванням)
console.log(role); // "user"
Деструктуризація в параметрах функції
Дуже поширений патерн:
// Без деструктуризації
function greet(user) {
console.log(`Привіт, ${user.name}! Тобі ${user.age} років.`);
}
// З деструктуризацією — чистіше
function greet({ name, age }) {
console.log(`Привіт, ${name}! Тобі ${age} років.`);
}
greet({ name: "Олексій", age: 25 });
Деструктуризація в параметрах — must-know для React. Кожен компонент React отримує props саме так: function Button({ label, onClick }).
Деструктуризація масивів
Працює за позицією (на відміну від об'єктів — за ім'ям):
const colors = ["червоний", "зелений", "синій"];
const [first, second, third] = colors;
console.log(first); // "червоний"
console.log(second); // "зелений"
// Пропуск елементів
const [, , last] = colors;
console.log(last); // "синій"
// Swap двох змінних (без тимчасової!)
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
Spread оператор для об'єктів
... "розпаковує" об'єкт:
Копіювання
const original = { name: "Олексій", age: 25 };
const copy = { ...original };
copy.age = 30;
console.log(original.age); // 25 — оригінал не змінився
console.log(copy.age); // 30
Злиття об'єктів
const defaults = { theme: "light", language: "uk", fontSize: 16 };
const userSettings = { theme: "dark", fontSize: 18 };
const settings = { ...defaults, ...userSettings };
console.log(settings);
// { theme: "dark", language: "uk", fontSize: 18 }
// userSettings перезаписує defaults
Додавання/оновлення властивостей
const user = { name: "Олексій", age: 25 };
// Додати нову властивість
const userWithCity = { ...user, city: "Київ" };
// { name: "Олексій", age: 25, city: "Київ" }
// Оновити існуючу
const olderUser = { ...user, age: 26 };
// { name: "Олексій", age: 26 }
Spread — ключовий патерн для імутабельності (immutability). Замість мутації user.age = 26 створюєш новий об'єкт { ...user, age: 26 }. Чому це важливо — детально в наступному уроці. А в React та Redux це обов'язковий підхід.
Rest оператор для об'єктів
"Збирає" залишкові властивості:
const user = { name: "Олексій", age: 25, city: "Київ", email: "alex@test.com" };
const { name, ...rest } = user;
console.log(name); // "Олексій"
console.log(rest); // { age: 25, city: "Київ", email: "alex@test.com" }
Корисно для видалення властивості без delete:
const { password, ...safeUser } = userData;
// safeUser — все, крім password
Optional Chaining — ?.
Безпечний доступ до вкладених властивостей:
const user = {
name: "Олексій",
address: {
city: "Київ",
},
};
// Без optional chaining — потенційна помилка
// console.log(user.contacts.email); // ❌ TypeError!
// З optional chaining
console.log(user.contacts?.email); // undefined (не помилка)
console.log(user.address?.city); // "Київ"
console.log(user.address?.street?.name); // undefined
Nullish Coalescing — ??
Значення за замовчуванням, якщо null або undefined:
const user = { name: "Олексій", age: 0 };
// || повертає default для будь-якого falsy (0, "")
console.log(user.age || 18); // 18 ❌ (0 — falsy!)
// ?? повертає default тільки для null/undefined
console.log(user.age ?? 18); // 0 ✅
console.log(user.email ?? "N/A"); // "N/A" (undefined)
?. + ?? — потужна комбінація: user.address?.city ?? "Невідомо" — безпечно дістати значення або повернути default.
Практика
// 1. Злиття налаштувань
function mergeSettings(defaults, custom) {
return { ...defaults, ...custom };
}
const config = mergeSettings(
{ theme: "light", lang: "uk", debug: false },
{ theme: "dark", debug: true }
);
console.log(config); // { theme: "dark", lang: "uk", debug: true }
// 2. Витягнути дані з API-відповіді
const apiResponse = {
status: 200,
data: {
user: { id: 1, name: "Олексій", role: "admin" },
token: "abc123",
},
};
const { data: { user: { name, role }, token } } = apiResponse;
console.log(name, role, token); // "Олексій" "admin" "abc123"
// 3. Безпечне отримання
function getUserCity(user) {
return user?.address?.city ?? "Місто не вказано";
}
console.log(getUserCity({ address: { city: "Київ" } })); // "Київ"
console.log(getUserCity({})); // "Місто не вказано"
console.log(getUserCity(null)); // "Місто не вказано"
Підсумок
- Destructuring:
const { name, age } = user— розпаковка об'єктів - Destructuring масивів:
const [a, b] = array— за позицією - Spread:
{ ...obj }— копіювання, злиття, immutable оновлення - Rest:
const { a, ...rest } = obj— збирає залишок - Optional chaining:
obj?.prop?.nested— безпечний доступ - Nullish coalescing:
value ?? default— default тільки для null/undefined
Що далі?
У наступному уроці розберемо мутабельність та імутабельність — чому spread створює "нову версію", а не змінює оригінал, і чому це критично для React.
Корисні посилання:
- javascript.info: Destructuring — повний гайд (українською)
- javascript.info: Spread та Rest — детально
- MDN: Optional Chaining — документація