Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

04.11 Spread operátor

Výuka

Proč Spread operátor?

Spread operátor ... "rozbalí" prvky pole (nebo iterable objektu) do jednotlivých hodnot. Je to moderní a elegantní způsob práce s poli.

Proč to potřebujeme?

  • Kopírování pole - Rychlá a čistá kopie bez mutace
  • Spojování polí - Sloučit více polí do jednoho
  • Předávání argumentů - Rozbal pole jako argumenty funkce
  • Immutability - Vytvoř nové pole místo změny originálu

Představ si to jako: Krabici s míčky. Spread operátor ... vysype všechny míčky z krabice ven (rozbalení). Místo jedné krabice máš jednotlivé míčky, se kterými můžeš dále pracovat.

Jak to funguje?

Spread operátor (...arr):
1. "Rozbalí" prvky pole do jednotlivých hodnot
2. [1, 2, 3]  1, 2, 3
3. Používá se v místech, kde se očekává více hodnot:
   - V novém poli: [...arr]
   - Jako argumenty funkce: fn(...arr)
   - Ve spojování polí: [...arr1, ...arr2]

Klíčové koncepty

  • Spread operátor ... - rozbalí prvky pole do jednotlivých hodnot
  • Shallow copy - vytvoří kopii pole (pozor u objektů!)
  • Immutability - neměnný způsob práce s poli
  • Iterable - funguje s poli, stringy, Set, Map, apod.
  • Rest parameter - opačný koncept (...args ve funkci sbírá argumenty)

JavaScript

Příklad 1: Kopírování pole (shallow copy)

const original = [1, 2, 3];

// Kopie pomocí spread operátoru
const copy = [...original];
console.log(copy);
// → [1, 2, 3]

// Je to NOVÝ objekt
console.log(copy === original);
// → false (různé objekty)

// Změna kopie neovlivní originál
copy.push(4);
console.log(original);  // → [1, 2, 3] (nezměněno)
console.log(copy);      // → [1, 2, 3, 4]

Co se stalo?

  • [...original] vytvoří novou kopii pole
  • Kopie je samostatný objekt (jiná reference)
  • Změny v kopii neovlivní originál
  • Pozor: Shallow copy - objekty uvnitř se kopírují jako reference!

Příklad 2: Spojování polí (concatenation)

const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [5, 6];

// Spojení pomocí spread
const combined = [...arr1, ...arr2, ...arr3];
console.log(combined);
// → [1, 2, 3, 4, 5, 6]

// Můžeš přidat i další prvky
const extended = [0, ...arr1, 99, ...arr2, 100];
console.log(extended);
// → [0, 1, 2, 99, 3, 4, 100]

// Porovnání s concat()
const combined2 = arr1.concat(arr2, arr3);
console.log(combined2);
// → [1, 2, 3, 4, 5, 6] (stejný výsledek)

Co se stalo?

  • [...arr1, ...arr2] sloučí pole do jednoho nového
  • Můžeš kombinovat více polí a další prvky
  • Čitelnější než concat()

Příklad 3: Přidání prvků immutabilně

const numbers = [2, 3, 4];

// Přidej na začátek (immutabilně)
const withFirst = [1, ...numbers];
console.log(withFirst);
// → [1, 2, 3, 4]

// Přidej na konec (immutabilně)
const withLast = [...numbers, 5];
console.log(withLast);
// → [2, 3, 4, 5]

// Přidej uprostřed
const withMiddle = [...numbers.slice(0, 2), 99, ...numbers.slice(2)];
console.log(withMiddle);
// → [2, 3, 99, 4]

// Originál zůstal netknutý
console.log(numbers);
// → [2, 3, 4]

Co se stalo?

  • Spread vytváří nová pole bez mutace originálu
  • Vhodné pro React/Redux (immutabilní state)
  • Alternativa k push, unshift, splice

Příklad 4: Předávání argumentů funkci

function sum(a, b, c) {
  return a + b + c;
}

const numbers = [1, 2, 3];

// Bez spread - předáš pole (nefunguje)
console.log(sum(numbers));
// → NaN (numbers je pole, ne 3 čísla)

// Se spread - rozbal pole na argumenty
console.log(sum(...numbers));
// → 6 (ekvivalentní sum(1, 2, 3))

// Praktický příklad - Math.max
const nums = [10, 5, 30, 15];
console.log(Math.max(...nums));
// → 30 (Math.max nemá verzi pro pole!)

Co se stalo?

  • ...numbers rozbalí pole [1, 2, 3] na 1, 2, 3
  • Funkce dostane jednotlivé argumenty, ne pole
  • Užitečné pro funkce, které očekávají více argumentů

Příklad 5: Spread s řetězci (string je iterable)

const text = 'hello';

// Rozbal string na pole znaků
const chars = [...text];
console.log(chars);
// → ['h', 'e', 'l', 'l', 'o']

// Porovnej s Array.from()
const chars2 = Array.from(text);
console.log(chars2);
// → ['h', 'e', 'l', 'l', 'o'] (stejný výsledek)

// Spread funguje s jakýmkoli iterable
const set = new Set([1, 2, 3]);
const arrFromSet = [...set];
console.log(arrFromSet);
// → [1, 2, 3]

Co se stalo?

  • Spread funguje s jakýmkoli iterable objektem
  • String, pole, Set, Map, atd.
  • Rychlý způsob převodu na pole

Příklad 6: Shallow copy - pozor u objektů!

const arr = [{ name: 'Alice' }, { name: 'Bob' }];

// Shallow copy
const copy = [...arr];

// Změň objekt v kopii
copy[0].name = 'Charlie';

// Originál SE ZMĚNIL! (objekty se kopírují jako reference)
console.log(arr[0].name);
// → Charlie (POZOR!)

// Deep copy - musíš použít jiné metody
const deepCopy = JSON.parse(JSON.stringify(arr));  // Deep copy
deepCopy[1].name = 'David';
console.log(arr[1].name);
// → Bob (nezměněno)

Co se stalo?

  • Spread vytváří shallow copy - kopíruje jen první úroveň
  • Objekty uvnitř pole se kopírují jako reference
  • Pro deep copy použij JSON.parse(JSON.stringify()) nebo knihovnu (lodash)

TypeScript

TypeScript přidává typovou kontrolu a readonly pole.

Stejné příklady s typy

// Kopírování s typy
const original: number[] = [1, 2, 3];
const copy: number[] = [...original];

// Spojování s typy
const arr1: number[] = [1, 2];
const arr2: number[] = [3, 4];
const combined: number[] = [...arr1, ...arr2];

// Můžeš kombinovat různé typy
const nums: number[] = [1, 2];
const strs: string[] = ['a', 'b'];
const mixed: (number | string)[] = [...nums, ...strs];  // [1, 2, 'a', 'b']

// Objekty s interface
interface User {
  name: string;
  age: number;
}

const users: User[] = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 }
];

const copy: User[] = [...users];

// Readonly pole - můžeš použít spread pro kopii
const readonly: readonly number[] = [1, 2, 3];
const mutable: number[] = [...readonly];  // ✅ OK - kopie je mutovatelná

// Spread s generickým typem
function clone<T>(arr: T[]): T[] {
  return [...arr];
}

const cloned: number[] = clone([1, 2, 3]);

// Chybová kontrola - musí být iterable
const obj = { a: 1, b: 2 };
// const arr = [...obj];  // ❌ Error: Type '{ a: number; b: number; }' is not an array type or a string type

// Spread u objektů funguje (ES2018+)
const objCopy = { ...obj };  // ✅ OK - { a: 1, b: 2 }

TypeScript přidává:

  • Typovou kontrolu - spread musí být použit na iterable
  • Inference typů - TypeScript pozná typ výsledku
  • Readonly kontrolu - můžeš vytvořit mutovatelnou kopii z readonly pole
  • Generické funkce - typově bezpečné utility funkce

Rozdíl JS vs TS

JavaScript:

  • Spread funguje bez typové kontroly
  • Můžeš omylem použít spread na ne-iterable
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • Spread je typově kontrolovaný
  • TypeScript zkontroluje, že používáš spread na iterable
  • Bezpečnější, prevence chyb
// JavaScript - runtime error
const obj = { a: 1, b: 2 };
const arr = [...obj];  // TypeError: obj is not iterable

// TypeScript - compile error
const obj = { a: 1, b: 2 };
const arr = [...obj];  // ❌ Error: Type is not an array type or a string type

Tip

💡 Používej spread pro immutabilní operace:

// ❌ Mutace originálu
const arr = [1, 2, 3];
arr.push(4);

// ✅ Immutabilní přidání
const newArr = [...arr, 4];

// ✅ Vhodné pro React state
setState([...state, newItem]);

💡 Spread je shallow copy - pozor u objektů:

const arr = [{ x: 1 }];

// ❌ Shallow copy - objekty se kopírují jako reference
const copy = [...arr];
copy[0].x = 2;  // Změní i originál!

// ✅ Deep copy
const deepCopy = JSON.parse(JSON.stringify(arr));

💡 Spread vs concat - čitelnost:

// ❌ Méně čitelné
const result = arr1.concat(arr2).concat(arr3);

// ✅ Čitelnější
const result = [...arr1, ...arr2, ...arr3];

Kvíz

Co vypíše tento kód?

const arr1 = [1, 2];
const arr2 = [...arr1, 3];
arr2.push(4);
console.log(arr1.length);

- [...arr1, 3] vytvoří NOVÉ pole [1, 2, 3] (kopie arr1 + prvek 3). arr2.push(4) přidá prvek do arr2, ale NEOVLIVNÍ arr1, protože jsou to různé objekty. arr1 stále obsahuje [1, 2], tedy délka je 2

- arr1 se nezměnilo

- Délka arr2 je 4, ne arr1

- Kód je validní

Důležité: Spread operátor vytváří novou kopii, takže změny v kopii neovlivní originál!

Důležité: Spread operátor vytváří novou kopii, takže změny v kopii neovlivní originál!

🎯 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 →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

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


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě