04.13 Map kolekce
Výuka
Proč Map?
Map je vestavěná datová struktura pro uložení párů klíč-hodnota. Na rozdíl od obyčejných objektů může mít klíče jakéhokoliv typu (ne jen stringy) a zachovává pořadí vložení.
Proč to potřebujeme?
- Flexibilní klíče - Klíče mohou být čísla, objekty, funkce (ne jen stringy)
- Zachování pořadí - Páry se iterují v pořadí vložení
- Rychlé operace -
get,set,has,deletejsou rychlé (O(1)) - Lepší API -
size,clear,forEach- pohodlnější než u objektů
Představ si to jako: Slovník. Máš slova (klíče) a jejich definice (hodnoty). Na rozdíl od obyčejného objektu může být "slovo" cokoli - číslo, jiný objekt, dokonce funkce!
Jak to funguje?
Map:
1. Ukládá páry klíč → hodnota
2. Klíč může být JAKÉHOKOLIV typu (číslo, string, objekt, funkce)
3. Zachovává pořadí vložení
4. Rychlé operace: set, get, has, delete (O(1) v průměru)
5. size - počet párů (ne length!)
Klíčové koncepty
Map- kolekce párů klíč-hodnota- Libovolné klíče - klíč může být jakýkoliv typ (ne jen string!)
size- počet párů (nelength!)- Metody:
set(),get(),has(),delete(),clear() - Iterable - můžeš iterovat přes páry, klíče nebo hodnoty
- Zachovává pořadí - iterace v pořadí vložení
JavaScript
Příklad 1: Vytvoření Map a základní operace
// Prázdná Map
const map1 = new Map();
console.log(map1);
// → Map(0) {}
// Map s počátečními hodnotami (z pole párů)
const map2 = new Map([
['name', 'Alice'],
['age', 25],
['city', 'Praha']
]);
console.log(map2);
// → Map(3) {'name' => 'Alice', 'age' => 25, 'city' => 'Praha'}
// Počet párů
console.log(map2.size);
// → 3
Co se stalo?
new Map()- vytvoří prázdnou Mapnew Map([[k1, v1], [k2, v2]])- vytvoří Map z pole párůsize- počet párů (nelength!)
Příklad 2: set() a get() - uložení a získání hodnoty
const map = new Map();
// Ulož páry klíč-hodnota
map.set('name', 'Bob');
map.set('age', 30);
map.set('active', true);
console.log(map);
// → Map(3) {'name' => 'Bob', 'age' => 30, 'active' => true}
// Získej hodnotu podle klíče
console.log(map.get('name'));
// → Bob
console.log(map.get('age'));
// → 30
// Neexistující klíč vrátí undefined
console.log(map.get('city'));
// → undefined
// Můžeš řetězit (chaining)
map.set('x', 1).set('y', 2).set('z', 3);
console.log(map.size);
// → 6
Co se stalo?
set(key, value)- uloží pár (nebo aktualizuje, pokud klíč existuje)get(key)- vrací hodnotu (neboundefined)- Vrací
Mapsamotnou → můžeš řetězit:map.set(...).set(...)
Příklad 3: Klíče jakéhokoliv typu (ne jen stringy!)
const map = new Map();
// String jako klíč
map.set('text', 'hodnota');
// Číslo jako klíč
map.set(42, 'odpověď na všechno');
// Boolean jako klíč
map.set(true, 'pravda');
// Objekt jako klíč (!)
const obj = { id: 1 };
map.set(obj, 'metadata');
// Funkce jako klíč (!)
const fn = () => {};
map.set(fn, 'callback');
console.log(map.get(42)); // → odpověď na všechno
console.log(map.get(obj)); // → metadata
console.log(map.get(fn)); // → callback
// ⚠️ Pozor - různé objekty se stejným obsahem jsou RŮZNÉ klíče
const obj2 = { id: 1 };
console.log(map.get(obj2));
// → undefined (obj !== obj2, různé reference!)
Co se stalo?
- Klíče můžou být cokoli: číslo, string, boolean, objekt, funkce
- Objekty se porovnávají podle reference, ne obsahu
- To je hlavní výhoda Map oproti obyčejným objektům!
Příklad 4: has() a delete() - kontrola a odstranění
const map = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
// Kontrola existence klíče
console.log(map.has('b'));
// → true
console.log(map.has('z'));
// → false
// Odstranění páru
const removed = map.delete('b');
console.log(removed);
// → true (pár byl odstraněn)
console.log(map);
// → Map(2) {'a' => 1, 'c' => 3}
// Pokus o odstranění neexistujícího klíče
const notRemoved = map.delete('z');
console.log(notRemoved);
// → false (klíč tam nebyl)
// Vymazání celé Map
map.clear();
console.log(map.size);
// → 0
Co se stalo?
has(key)- vracítrue/falsedelete(key)- odstraní pár, vracítrue/falseclear()- vymaže všechny páry
Příklad 5: Iterace přes Map
const map = new Map([
['name', 'Alice'],
['age', 25],
['city', 'Praha']
]);
// for...of přes páry (entries)
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
// → name: Alice
// → age: 25
// → city: Praha
// Iterace jen přes klíče
for (const key of map.keys()) {
console.log(key);
}
// → name
// → age
// → city
// Iterace jen přes hodnoty
for (const value of map.values()) {
console.log(value);
}
// → Alice
// → 25
// → Praha
// forEach
map.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// → name = Alice
// → age = 25
// → city = Praha
Co se stalo?
- Defaultní iterace: přes páry
[key, value] keys()- iterátor přes klíčevalues()- iterátor přes hodnotyentries()- iterátor přes páry (stejné jako defaultní)- Zachovává pořadí vložení!
Příklad 6: Map vs obyčejný objekt
// Obyčejný objekt - klíče jsou VŽDY stringy
const obj = {};
obj[1] = 'hodnota'; // klíč se převede na '1'
obj[true] = 'bool'; // klíč se převede na 'true'
console.log(Object.keys(obj));
// → ['1', 'true'] (stringy!)
// Map - klíče NEJSOU převáděny na stringy
const map = new Map();
map.set(1, 'hodnota');
map.set(true, 'bool');
console.log([...map.keys()]);
// → [1, true] (původní typy!)
// Objekt - size ručně
console.log(Object.keys(obj).length);
// → 2 (musíš spočítat)
// Map - size přímo
console.log(map.size);
// → 2 (vlastnost)
// Objekt - iterace složitější
for (const key in obj) {
console.log(`${key}: ${obj[key]}`);
}
// Map - iterace jednodušší
for (const [key, value] of map) {
console.log(`${key}: ${value}`);
}
Co se stalo?
- Objekt: klíče vždy stringy, složitější API
- Map: klíče libovolného typu, lepší API
- Kdy použít Map:
- Potřebuješ klíče jiného typu než string
- Často přidáváš/odstraňuješ páry
- Záleží ti na pořadí
- Kdy použít objekt:
- Potřebuješ JSON (Map se neserializuje)
- Klíče jsou známé předem (statická struktura)
TypeScript
TypeScript přidává typovou kontrolu klíčů a hodnot.
Stejné příklady s typy
// Map s typy
const map1: Map<string, number> = new Map([
['age', 25],
['score', 100]
]);
// TypeScript inferuje typ z pole
const map2 = new Map([
['name', 'Alice'],
['city', 'Praha']
]); // Map<string, string>
// Chybová kontrola - špatný typ klíče nebo hodnoty
map1.set('count', 50); // ✅ OK
// map1.set('count', 'text'); // ❌ Error: Argument of type 'string' is not assignable to parameter of type 'number'
// map1.set(123, 50); // ❌ Error: Argument of type 'number' is not assignable to parameter of type 'string'
// Objekty jako klíče s interface
interface User {
id: number;
name: string;
}
const userMap: Map<User, string> = new Map();
const user1: User = { id: 1, name: 'Alice' };
userMap.set(user1, 'metadata');
const meta: string | undefined = userMap.get(user1);
// Generická utility funkce
function mapFromEntries<K, V>(entries: [K, V][]): Map<K, V> {
return new Map(entries);
}
const numMap = mapFromEntries([[1, 'one'], [2, 'two']]); // Map<number, string>
// ReadonlyMap (TypeScript 3.4+)
const readonly: ReadonlyMap<string, number> = new Map([['a', 1]]);
// readonly.set('b', 2); // ❌ Error: Property 'set' does not exist on type 'ReadonlyMap<string, number>'
console.log(readonly.get('a')); // ✅ OK - čtení je povoleno
TypeScript přidává:
- ✅ Typovou kontrolu klíčů a hodnot - nemůžeš uložit špatný typ
- ✅ Inference typů - TypeScript pozná typ z pole
- ✅ ReadonlyMap - neměnná Map (jen čtení)
- ✅ Generické funkce - typově bezpečné utility funkce
Rozdíl JS vs TS
JavaScript:
- Map funguje bez typové kontroly
- Můžeš uložit jakýkoliv typ klíče a hodnoty
- Flexibilnější, ale nebezpečnější
TypeScript:
- Map má definované typy klíčů a hodnot
- TypeScript zkontroluje, že ukládáš správné typy
- Bezpečnější, prevence chyb
// JavaScript - projde, ale matoucí
const map = new Map();
map.set('text', 123);
map.set(456, 'hodnota'); // Smíšené typy klíčů a hodnot
// TypeScript - konzistentní typy
const map: Map<string, number> = new Map();
map.set('text', 123);
// map.set(456, 'hodnota'); // ❌ Error
Tip
💡 Kdy použít Map místo objektu:
// ✅ Používej Map když:
// - Klíče nejsou stringy
// - Často přidáváš/odstraňuješ páry
// - Záleží ti na pořadí
// - Potřebuješ size property
// ✅ Používej objekt když:
// - Potřebuješ JSON (Map se neserializuje)
// - Klíče jsou známé předem
// - Struktura je statická
💡 Prevence chyb s objektovými klíči:
const map = new Map();
const key1 = { id: 1 };
const key2 = { id: 1 };
map.set(key1, 'hodnota');
// ❌ Chyba - key2 !== key1 (různé reference)
console.log(map.get(key2)); // → undefined
// ✅ Používej stejnou referenci
console.log(map.get(key1)); // → hodnota
💡 Převod Map na objekt a zpět:
// Map → objekt
const map = new Map([['a', 1], ['b', 2]]);
const obj = Object.fromEntries(map);
console.log(obj); // → { a: 1, b: 2 }
// Objekt → Map
const obj2 = { x: 10, y: 20 };
const map2 = new Map(Object.entries(obj2));
console.log(map2); // → Map(2) {'x' => 10, 'y' => 20}
Kvíz
Co vypíše tento kód?
const map = new Map();
map.set('a', 1);
map.set('a', 2);
map.set('b', 3);
console.log(map.size);
✅ - - map.set('a', 1) - přidá pár 'a' => 1 (size = 1)
map.set('a', 2)- aktualizuje hodnotu pro klíč'a'na 2 (size = 1, stále jen 1 pár!)map.set('b', 3)- přidá pár'b' => 3(size = 2)- Finální:
Map(2) {'a' => 2, 'b' => 3}
❌ - Zapomněl jsi, že druhý set('a', 2) aktualizuje, nepřidává
❌ - Každý set nepřidává nový pár, může aktualizovat
❌ - Chybný výpočet
Důležité: Když set() najde existující klíč, aktualizuje hodnotu, nepřidává nový pár!
Důležité: Když set() najde existující klíč, aktualizuje hodnotu, nepřidává nový pár!
🎯 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
- 04.01 Vytvoření pole
- 04.02 Přístup k prvkům
- 04.03 Push, pop, shift, unshift
- 04.04 Slice a splice
- 04.06 Filter
- 04.07 Reduce
- 04.08 Find a findIndex
- 04.09 Some a every
- 04.10 Sort
- 04.11 Spread operátor
- 04.12 Set
- 04.13 Map kolekce
- 04.14 Destructuring polí
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ě