05.8 Nullish coalescing
Výuka
Proč nullish coalescing?
Nullish coalescing operátor (??) vrací pravou hodnotu, pokud levá je null nebo undefined. Na rozdíl od || nenahrazuje falsy hodnoty jako 0, '', false.
Proč to potřebujeme?
- Default hodnoty - Nastav default jen pro
null/undefined - Přesnější než
||-0,'',falsejsou validní hodnoty - Bezpečný fallback - Vrať alternativu jen když hodnota chybí
- Kombinace s
?.- Bezpečný přístup + default hodnota
Představ si to jako: Záložní plán. Pokud tvůj hlavní plán neexistuje (null/undefined), použiješ záložní. Ale pokud hlavní plán je "nic nedělat" (0, '', false), to je stále validní plán!
Jak to funguje?
Nullish coalescing (a ?? b):
1. Pokud a je null NEBO undefined → vrať b
2. Jinak vrať a
3. NENAHRAZUJE falsy hodnoty (0, '', false) - jen null/undefined
Klíčové koncepty
- Nullish coalescing
??- vrať pravou hodnotu jen pro null/undefined - Nullish values -
nullaundefined(ne ostatní falsy!) - ES2020 feature - od ES2020
- Rozdíl od
||-||nahrazuje všechny falsy hodnoty - Short-circuit - pokud levá strana není null/undefined, pravá se nevyhodnotí
JavaScript
Příklad 1: Základní nullish coalescing
const user = {
name: 'Alice',
age: 25
};
// Pokud vlastnost existuje - vrať ji
const userName = user.name ?? 'Anonym';
console.log(userName);
// → Alice
// Pokud vlastnost neexistuje - vrať default
const userEmail = user.email ?? 'no-email@example.com';
console.log(userEmail);
// → no-email@example.com
// Null hodnota - vrať default
const user2 = {
name: 'Bob',
email: null
};
const email = user2.email ?? 'default@example.com';
console.log(email);
// → default@example.com
Co se stalo?
a ?? b- pokudajenullneboundefined, vraťb- Jinak vrať
a - Užitečné pro default hodnoty
Příklad 2: Rozdíl mezi ?? a ||
const settings = {
volume: 0, // 0 je validní hodnota!
muted: false, // false je validní hodnota!
theme: '', // '' je validní hodnota!
language: undefined
};
// S || - ŠPATNĚ!
console.log(settings.volume || 50);
// → 50 (CHYBA! 0 je falsy, ale validní hodnota)
console.log(settings.muted || true);
// → true (CHYBA! false je falsy, ale validní hodnota)
console.log(settings.theme || 'light');
// → light (CHYBA! '' je falsy, ale validní hodnota)
// S ?? - SPRÁVNĚ!
console.log(settings.volume ?? 50);
// → 0 (SPRÁVNĚ! 0 není null/undefined)
console.log(settings.muted ?? true);
// → false (SPRÁVNĚ! false není null/undefined)
console.log(settings.theme ?? 'light');
// → '' (SPRÁVNĚ! '' není null/undefined)
console.log(settings.language ?? 'cs');
// → cs (SPRÁVNĚ! undefined → použij default)
Co se stalo?
||nahrazuje VŠECHNY falsy (0,'',false,null,undefined,NaN)??nahrazuje JENnullaundefined- Pro default hodnoty preferuj
??- přesnější!
Příklad 3: Kombinace s optional chaining
const user = {
name: 'Charlie',
preferences: {
theme: 'dark'
}
};
// Optional chaining + nullish coalescing
const theme = user?.preferences?.theme ?? 'light';
console.log(theme);
// → dark
const user2 = {
name: 'David'
// preferences neexistuje
};
const theme2 = user2?.preferences?.theme ?? 'light';
console.log(theme2);
// → light
// Praktický příklad - API response
const apiResponse = {
data: {
user: {
name: 'Eve',
settings: {
notifications: true
}
}
}
};
const notifications = apiResponse?.data?.user?.settings?.notifications ?? false;
console.log(notifications);
// → true
const apiResponse2 = {};
const notifications2 = apiResponse2?.data?.user?.settings?.notifications ?? false;
console.log(notifications2);
// → false
Co se stalo?
?.+??- kombinace pro bezpečný přístup s default hodnotouobj?.prop ?? default- vrať vlastnost nebo default- Velmi užitečné pro API responses a neúplná data
Příklad 4: Řetězení nullish coalescing
const config = {
userSettings: undefined,
defaultSettings: null,
fallbackSettings: {
theme: 'light',
fontSize: 14
}
};
// Řetězení - první ne-null/undefined vyhrává
const settings = config.userSettings ?? config.defaultSettings ?? config.fallbackSettings;
console.log(settings);
// → { theme: 'light', fontSize: 14 }
// Praktický příklad - více úrovní fallbacku
function getPort() {
return undefined;
}
const port = process.env.PORT ?? getPort() ?? 3000;
console.log(port);
// → 3000 (process.env.PORT je undefined, getPort() vrací undefined)
Co se stalo?
- Řetězení:
a ?? b ?? c- první ne-null/undefined vyhrává - Užitečné pro více úrovní fallbacku
- Short-circuit - zastaví se u první validní hodnoty
Příklad 5: Nullish coalescing assignment (??=)
let config = {
theme: 'dark'
};
// Přiřaď jen pokud vlastnost je null/undefined
config.theme ??= 'light';
console.log(config.theme);
// → dark (theme už existuje, nepřepíše se)
config.fontSize ??= 14;
console.log(config.fontSize);
// → 14 (fontSize neexistoval, přiřadil se)
// Ekvivalentní k:
config.theme = config.theme ?? 'light';
config.fontSize = config.fontSize ?? 14;
// Praktický příklad - inicializace defaults
const userSettings = {
volume: 0 // 0 je validní!
};
userSettings.volume ??= 50;
console.log(userSettings.volume);
// → 0 (SPRÁVNĚ! 0 není null/undefined, nepřepíše se)
userSettings.theme ??= 'light';
console.log(userSettings.theme);
// → light (theme neexistoval, přiřadil se)
Co se stalo?
??=- nullish coalescing assignment- Přiřaď hodnotu jen pokud vlastnost je
nullneboundefined - Užitečné pro inicializaci defaults
Příklad 6: Použití s funkcemi
function greet(name) {
const displayName = name ?? 'Guest';
return `Hello, ${displayName}!`;
}
console.log(greet('Alice'));
// → Hello, Alice!
console.log(greet(undefined));
// → Hello, Guest!
console.log(greet(null));
// → Hello, Guest!
console.log(greet(''));
// → Hello, ! ('' není null/undefined!)
// Lepší verze - kontrola i prázdného stringu
function greet2(name) {
const displayName = name || 'Guest'; // Použij || pro prázdný string
return `Hello, ${displayName}!`;
}
console.log(greet2(''));
// → Hello, Guest!
// Nebo kombinace
function greet3(name) {
const displayName = (name ?? '').trim() || 'Guest';
return `Hello, ${displayName}!`;
}
console.log(greet3(''));
// → Hello, Guest!
console.log(greet3(' '));
// → Hello, Guest! (whitespace oříznut)
console.log(greet3('Alice'));
// → Hello, Alice!
Co se stalo?
??v parametrech - default hodnota pro null/undefined- Pro prázdné stringy použij
||(pokud je chceš nahradit) - Můžeš kombinovat
??a||podle potřeby
TypeScript
TypeScript přidává typovou kontrolu nullish coalescing.
Stejné příklady s typy
// Základní použití s typy
const user: { name: string; email?: string } = {
name: 'Alice'
};
const email: string = user.email ?? 'no-email@example.com';
// TypeScript inferuje: string
// S union types
type Config = {
port: number | null | undefined;
host: string | null;
};
const config: Config = {
port: null,
host: null
};
const port: number = config.port ?? 3000;
const host: string = config.host ?? 'localhost';
// Type narrowing
function getPort(config: Config): number {
return config.port ?? 3000; // ✅ TypeScript ví, že výsledek je number
}
// Nullish coalescing s optional properties
interface User {
name: string;
age?: number;
email?: string | null;
}
const user: User = {
name: 'Bob'
};
const age: number = user.age ?? 0;
const email: string = user.email ?? 'no-email';
// Generické funkce
function getOrDefault<T>(value: T | null | undefined, defaultValue: T): T {
return value ?? defaultValue;
}
const result1: number = getOrDefault(null, 42); // → 42
const result2: string = getOrDefault('hello', 'default'); // → hello
const result3: number = getOrDefault(0, 42); // → 0 (0 není null!)
// S strictNullChecks
const maybeString: string | null = Math.random() > 0.5 ? 'value' : null;
const definiteString: string = maybeString ?? 'default';
// TypeScript ví, že definiteString je vždy string
TypeScript přidává:
- ✅ Typovou kontrolu - TypeScript ví, že výsledek nikdy není null/undefined
- ✅ Type narrowing - lepší inference typů
- ✅ Union types -
T | null | undefined - ✅ Prevenci chyb - upozorní na možné problémy
Rozdíl JS vs TS
JavaScript:
??funguje bez typové kontroly- Musíš ručně kontrolovat typy
- Flexibilnější, ale nebezpečnější
TypeScript:
- TypeScript ví, že výsledek nikdy není null/undefined
- Lepší type narrowing
- Bezpečnější, prevence chyb
// JavaScript - musíš ručně kontrolovat
const value = config.port ?? 3000;
// value může být number nebo cokoliv jiného
// TypeScript - type narrowing
interface Config {
port: number | null;
}
const config: Config = { port: null };
const value: number = config.port ?? 3000;
// TypeScript ví, že value je VŽDY number
Tip
💡 Preferuj ?? místo || pro default hodnoty:
// ❌ || nahrazuje 0, '', false (problém!)
const volume = settings.volume || 50; // 0 → 50 (CHYBA!)
// ✅ ?? nahrazuje jen null/undefined
const volume = settings.volume ?? 50; // 0 → 0 (SPRÁVNĚ!)
💡 Kombinuj ?. s ?? pro bezpečný přístup:
// ✅ Bezpečný přístup + default hodnota
const city = user?.address?.city ?? 'Unknown';
// Místo
const city = (user && user.address && user.address.city) || 'Unknown';
💡 Používej ??= pro inicializaci defaults:
// ✅ Inicializuj jen pokud neexistuje
config.theme ??= 'light';
config.fontSize ??= 14;
// Místo
if (config.theme === null || config.theme === undefined) {
config.theme = 'light';
}
Kvíz
Co vypíše tento kód?
const settings = {
volume: 0,
muted: false
};
console.log(settings.volume ?? 50);
console.log(settings.volume || 50);
❌ - || nahrazuje falsy hodnoty, včetně 0
❌ - ?? nenahrazuje 0, jen null/undefined
✅ - - settings.volume ?? 50:
- settings.volume = 0
- 0 NENÍ null ani undefined
- ?? vrací 0 (levou hodnotu)
settings.volume || 50:settings.volume=00je falsy hodnota||vrací50(pravou hodnotu)
❌ - Obrácené hodnoty
Důležité: ?? nahrazuje JEN null a undefined, zatímco || nahrazuje VŠECHNY falsy hodnoty (0, '', false, null, undefined, NaN)!
Důležité: ?? nahrazuje JEN null a undefined, zatímco || nahrazuje VŠECHNY falsy hodnoty (0, '', false, null, undefined, NaN)!
🎯 Závěrečný projekt
Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.
Zobrazit podrobnosti projektu →Informace o seriálu
Obtížnost
Délka
Cca 480 minut
Počet videí
8 videí + projekty
Certifikát
Po dokončení obdržíte certifikát
Lekce v této sekci
- 05.1 Vytvoření objektu
- 05.2 Vlastnosti
- 05.3 Metody objektu
- 05.4 This keyword
- 05.5 Destructuring objektů
- 05.6 Spread u objektů
- 05.7 Optional chaining
- 05.8 Nullish coalescing
- 05.9 Object.keys/values/entries
- 05.10 Computed properties
- 05.11 Getters a setters
- 05.12 Object.freeze/seal
Struktura lekcí (souborový strom)
- 1.1 Úvod do JavaScriptu a TypeScriptu
- 1.2 Nastavení prostředí
- 1.3 První program
- 1.4 Proměnné: var, let, const
- 1.5 Datové typy - přehled
- 1.6 String (řetězce)
- 1.7 Number (čísla)
- 1.8 Boolean (pravda/nepravda)
- 1.9 Null a Undefined
- 1.10 Type Inference vs Annotations
- 1.11 Aritmetické operátory
- 1.12 Porovnávací operátory
- 1.13 Logické operátory
- 1.14 Komentáře
- 1.15 Console metody
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
- v přípravě
- v přípravě
- v přípravě
- v přípravě
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
- v přípravě
- v přípravě
- v přípravě