ES6+ — частина 2
JavaScript ES6+ optional chaining — садова стежка з каменів-сходинок над ставком де деякі шляхи зникають у тумані
Продовжуємо вивчати сучасний JavaScript. У цьому уроці — фічі з ES2019-ES2023, які роблять код безпечнішим та лаконічнішим.
Optional Chaining — ?.
Ми вже зустрічали ?. у Block 4. Поглибимо знання:
const user = {
name: "Олексій",
address: { city: "Київ" },
};
// Безпечний доступ до вкладених властивостей
console.log(user.address?.city); // "Київ"
console.log(user.contacts?.email); // undefined (замість TypeError)
// Для методів
console.log(user.getName?.()); // undefined (метод не існує)
// Для масивів
const arr = [1, 2, 3];
console.log(arr?.[5]); // undefined
Ланцюжки
const response = {
data: {
users: [
{ name: "Олексій", settings: { theme: "dark" } },
],
},
};
const theme = response?.data?.users?.[0]?.settings?.theme;
console.log(theme); // "dark"
// Без optional chaining — купа перевірок:
const theme2 = response && response.data && response.data.users
&& response.data.users[0] && response.data.users[0].settings
&& response.data.users[0].settings.theme;
Nullish Coalescing — ??
Повертає правий операнд тільки якщо лівий null або undefined:
const count = 0;
const name = "";
// || замінює ВСІ falsy (0, "", false)
console.log(count || 10); // 10 ❌ (0 — валідне значення!)
console.log(name || "Гість"); // "Гість" ❌
// ?? замінює тільки null/undefined
console.log(count ?? 10); // 0 ✅
console.log(name ?? "Гість"); // "" ✅
console.log(null ?? "default"); // "default"
console.log(undefined ?? "default"); // "default"
Комбінація ?. та ??
function getUserTheme(user) {
return user?.settings?.theme ?? "light";
}
console.log(getUserTheme({ settings: { theme: "dark" } })); // "dark"
console.log(getUserTheme({})); // "light"
console.log(getUserTheme(null)); // "light"
Logical Assignment Operators
ES2021 додав скорочення для логічних операцій з присвоєнням:
||= (OR assignment)
let title = "";
title ||= "Без назви"; // якщо falsy → присвоїти
console.log(title); // "Без назви"
// Еквівалент: title = title || "Без назви"
??= (Nullish assignment)
let config = { theme: null, fontSize: 0 };
config.theme ??= "light"; // null → присвоїти
config.fontSize ??= 16; // 0 — не null, не присвоювати
console.log(config); // { theme: "light", fontSize: 0 }
&&= (AND assignment)
let user = { name: "Олексій", loggedIn: true };
user.loggedIn &&= false; // якщо truthy → присвоїти
console.log(user.loggedIn); // false
??= — найкорисніший з трьох. Ідеальний для встановлення значень за замовчуванням: options.timeout ??= 5000.
Корисні методи масивів (ES2019+)
Array.flat() — розгортання вкладених масивів
const nested = [1, [2, 3], [4, [5, 6]]];
console.log(nested.flat()); // [1, 2, 3, 4, [5, 6]]
console.log(nested.flat(2)); // [1, 2, 3, 4, 5, 6]
console.log(nested.flat(Infinity)); // [1, 2, 3, 4, 5, 6]
Array.flatMap() — map + flat
const sentences = ["Привіт світ", "Як справи"];
const words = sentences.flatMap((s) => s.split(" "));
console.log(words); // ["Привіт", "світ", "Як", "справи"]
at() — доступ за індексом (ES2022)
const arr = [10, 20, 30, 40, 50];
console.log(arr.at(0)); // 10
console.log(arr.at(-1)); // 50 (останній!)
console.log(arr.at(-2)); // 40
// Замість arr[arr.length - 1]
Object.groupBy() (ES2024)
const students = [
{ name: "Олексій", grade: "A" },
{ name: "Марія", grade: "B" },
{ name: "Іван", grade: "A" },
{ name: "Анна", grade: "B" },
];
const grouped = Object.groupBy(students, (s) => s.grade);
// { A: [{name:"Олексій",...}, {name:"Іван",...}], B: [...] }
Object.fromEntries()
Зворотна операція до Object.entries():
// entries → object
const entries = [["name", "Олексій"], ["age", 25]];
const obj = Object.fromEntries(entries);
console.log(obj); // { name: "Олексій", age: 25 }
// Практичний приклад: трансформація об'єкта
const prices = { apple: 10, banana: 15, cherry: 25 };
const doubled = Object.fromEntries(
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
console.log(doubled); // { apple: 20, banana: 30, cherry: 50 }
structuredClone() — глибока копія
const original = {
name: "Олексій",
hobbies: ["JS", "React"],
address: { city: "Київ" },
};
const clone = structuredClone(original);
clone.hobbies.push("TypeScript");
clone.address.city = "Львів";
console.log(original.hobbies); // ["JS", "React"] — не змінився
console.log(original.address.city); // "Київ" — не змінився
structuredClone() — сучасна заміна JSON.parse(JSON.stringify(obj)). Підтримує Date, Map, Set, RegExp та інші типи, які JSON не підтримує.
Підсумок
?.— безпечний доступ (замість ланцюжка&&)??— default тільки для null/undefined (краще за||для 0 та "")??=— присвоїти якщо null/undefined.at(-1)— останній елемент масиву.flat()— розгортання вкладених масивівObject.fromEntries()— масив пар → об'єктstructuredClone()— глибока копія
Що далі?
У наступному уроці вивчимо Promises — основу асинхронного JavaScript.
Корисні посилання:
- javascript.info: Optional chaining — українською
- MDN: Nullish coalescing — документація
- TC39 Proposals — всі майбутні фічі JavaScript