Mnoho vestavÄných funkcà v JavaScriptu umožÅuje uvést libovolný poÄet argumentů.
NapÅÃklad:
Math.max(arg1, arg2, ..., argN)â vrátà nejvÄtšà z argumentů.Object.assign(cÃl, zdroj1, ..., zdrojN)â zkopÃruje vlastnosti zezdroj1..NdocÃl.- â¦a tak dále.
V této kapitole se nauÄÃme, jak udÄlat totéž, a také, jak pÅedávat do takových funkcà pole jako parametry.
Zbytkové parametry ...
Funkci můžeme volat s libovolným poÄtem argumentů, bez ohledu na to, jak je definována.
NapÅÃklad zde:
function souÄet(a, b) {
return a + b;
}
alert( souÄet(1, 2, 3, 4, 5) );
Kvůli âpÅebyteÄnýmâ argumentům nenastane chyba, ale do výsledku se samozÅejmÄ budou poÄÃtat jen prvnà dva, takže výsledek v uvedeném kódu je 3.
Zbylé parametry můžeme zahrnout do definice funkce pomocà tÅà teÄek ..., za nimiž následuje název pole, které je bude obsahovat. TeÄky doslova znamenajà âshromáždi zbývajÃcà parametry do poleâ.
NapÅÃklad abychom shromáždili vÅ¡echny argumenty do pole argumenty:
function seÄtiVÅ¡e(...argumenty) { // argumenty je název pole
let souÄet = 0;
for (let arg of argumenty) souÄet += arg;
return souÄet;
}
alert( seÄtiVÅ¡e(1) ); // 1
alert( seÄtiVÅ¡e(1, 2) ); // 3
alert( seÄtiVÅ¡e(1, 2, 3) ); // 6
Můžeme se rozhodnout, že prvnà parametry uložÃme do promÄnných a shromáždÃme pouze ty ostatnÃ.
Zde budou prvnà dva argumenty uloženy do promÄnných a ostatnà se uložà do pole tituly:
function zobrazJméno(kÅestnÃJméno, pÅÃjmenÃ, ...tituly) {
alert( kÅestnÃJméno + ' ' + pÅÃjmenà ); // Julius Caesar
// ostatnà pÅijdou do pole tituly
// tj. tituly = ["Konzul", "Imperátor"]
alert( tituly[0] ); // Konzul
alert( tituly[1] ); // Imperátor
alert( tituly.length ); // 2
}
zobrazJméno("Julius", "Caesar", "Konzul", "Imperátor");
Pole zbytkových parametrů shromažÄuje vÅ¡echny zbývajÃcà argumenty, takže následujÃcà zápis nedává smysl a vyvolá chybu:
function f(arg1, ...zbytek, arg2) { // arg2 po ...zbytek ?!
// chyba
}
...zbytek musà být vždy poslednÃ.
PromÄnná âargumentsâ
Existuje také speciálnà objekt podobný poli nazvaný arguments, který obsahuje všechny argumenty uložené podle jejich indexu.
NapÅÃklad:
function zobrazJméno() {
alert( arguments.length );
alert( arguments[0] );
alert( arguments[1] );
// je iterovatelný
// for(let arg of arguments) alert(arg);
}
// zobrazÃ: 2, Julius, Caesar
zobrazJméno("Julius", "Caesar");
// zobrazÃ: 1, Ilja, undefined (druhý argument nenÃ)
zobrazJméno("Ilja");
V dÅÃvÄjÅ¡Ãch dobách zbytkové parametry v jazyce neexistovaly a jediný způsob, jak zÃskat vÅ¡echny argumenty funkce, bylo použità arguments. A to stále funguje, můžeme to nalézt ve starých kódech.
Nevýhodou vÅ¡ak je, že aÄkoli objekt arguments je podobný poli a iterovatelný, nenà to pole. Nepodporuje metody polÃ, takže nemůžeme volat napÅÃklad arguments.map(...).
NavÃc obsahuje vždy vÅ¡echny argumenty. Nemůžeme je zachytit jen ÄásteÄnÄ, jak to můžeme udÄlat u zbytkových parametrů.
Když tedy tuto vlastnost potÅebujeme, dáváme pÅednost zbytkovým parametrům.
âargumentsâJestliže pÅistoupÃme k objektu arguments v Å¡ipkové funkci, pÅevezme se z vnÄjšà ânormálnÃâ funkce.
PÅÃklad:
function f() {
let zobrazArgumenty = () => alert(arguments[0]);
zobrazArgumenty();
}
f(1); // 1
Jak si pamatujeme, Å¡ipkové funkce nemajà vlastnà this. Nynà vÃme, že nemajà ani speciálnà objekt arguments.
Roztažená syntaxe
PrávÄ jsme vidÄli, jak vytvoÅit pole ze seznamu parametrů.
NÄkdy vÅ¡ak potÅebujeme udÄlat pravý opak.
NapÅÃklad existuje vestavÄná funkce Math.max, která vracà nejvÄtšà ÄÃslo ze seznamu:
alert( Math.max(3, 5, 1) ); // 5
Nynà ÅeknÄme, že máme pole [3, 5, 1]. Jak na nÄ zavoláme Math.max?
PÅedat pole âtak, jak jeâ nebude fungovat, protože Math.max oÄekává seznam ÄÃselných argumentů, ne jediné pole:
let pole = [3, 5, 1];
alert( Math.max(pole) ); // NaN
A samozÅejmÄ nemůžeme v kódu ruÄnÄ vyjmenovat prvky pole Math.max(pole[0], pole[1], pole[2]), protože nevÃme jistÄ, kolik jich tam bude. Když se náš skript spustÃ, může jich tam být mnoho a nemusà tam být žádný. A to by mohlo Å¡patnÄ dopadnout.
Zachránà nás roztažená (spread) syntaxe! Podobá se zbytkovým parametrům v tom, že také použÃvá ..., ale Äinà to pÅesnÄ naopak.
Když ve volánà funkce použijeme ...pole, iterovatelný objekt pole se âroztáhneâ do seznamu argumentů.
Pro Math.max:
let pole = [3, 5, 1];
alert( Math.max(...pole) ); // 5 (roztaženà pÅetvoÅà pole na seznam argumentů)
TÃmto způsobem můžeme pÅedat i vÃce iterovatelných objektů:
let pole1 = [1, -2, 3, 4];
let pole2 = [8, 3, -8, 1];
alert( Math.max(...pole1, ...pole2) ); // 8
Můžeme dokonce kombinovat roztaženou syntaxi s bÄžnými hodnotami:
let pole1 = [1, -2, 3, 4];
let pole2 = [8, 3, -8, 1];
alert( Math.max(1, ...pole1, 2, ...pole2, 25) ); // 25
Roztaženou syntaxi můžeme použÃt i ke spojenà polÃ:
let pole = [3, 5, 1];
let pole2 = [8, 9, 15];
let spojené = [0, ...pole, 2, ...pole2];
alert(spojené); // 0,3,5,1,2,8,9,15 (0, pak pole, pak 2, pak pole2)
Ve výše uvedených pÅÃkladech jsme pÅi pÅedvádÄnà roztažené syntaxe použili pole, ale funguje to na jakémkoli iterovatelném objektu.
NapÅÃklad zde použijeme roztaženou syntaxi k pÅevedenà ÅetÄzce na pole znaků:
let ÅetÄzec = "Ahoj";
alert( [...ÅetÄzec] ); // A,h,o,j
Roztažená syntaxe vnitÅnÄ využÃvá iterátory ke shromažÄovánà prvků stejným způsobem, jako cyklus for..of.
Pro ÅetÄzec tedy for..of vrátà znaky a ...ÅetÄzec se pÅevede na "A","h","o","j". Seznam znaků se pÅedá do inicializátoru pole [...ÅetÄzec].
Pro tento konkrétnà úkol bychom mohli použÃt i Array.from, protože tato metoda pÅevádà iterovatelný objekt (napÅ. ÅetÄzec) na pole:
let ÅetÄzec = "Ahoj";
// Array.from pÅevede iterovatelný objekt na pole
alert( Array.from(ÅetÄzec) ); // A,h,o,j
Výsledek je stejný jako u [...ÅetÄzec].
Existuje vÅ¡ak drobný rozdÃl mezi Array.from(obj) a [...obj]:
Array.fromfunguje na objektech podobných poli i na iterovatelných objektech.- Roztažená syntaxe funguje jen na iterovatelných objektech.
Pro úÄel pÅevedenà nÄÄeho jiného na pole tedy Array.from bývá univerzálnÄjÅ¡Ã.
KopÃrovánà pole/objektu
Pamatujete si, jak jsme dÅÃve hovoÅili o Object.assign()?
S roztaženou syntaxà můžeme udÄlat totéž.
let pole = [1, 2, 3];
let kopiePole = [...pole]; // roztáhneme pole do seznamu parametrů
// pak uložÃme výsledek do nového pole
// majà tato pole stejný obsah?
alert(JSON.stringify(pole) === JSON.stringify(kopiePole)); // true
// jsou si tato pole rovna?
alert(pole === kopiePole); // false (nenà to stejný odkaz)
// modifikace naÅ¡eho původnÃho pole nezmÄnà kopii:
pole.push(4);
alert(pole); // 1, 2, 3, 4
alert(kopiePole); // 1, 2, 3
VÅ¡imnÄte si, že můžeme udÄlat totéž, abychom vytvoÅili kopii objektu:
let objekt = { a: 1, b: 2, c: 3 };
let kopieObjektu = { ...objekt }; // roztáhneme objekt do seznamu parametrů
// pak vrátÃme výsledek v novém objektu
// majà tyto objekty stejný obsah?
alert(JSON.stringify(objekt) === JSON.stringify(kopieObjektu)); // true
// jsou si tyto objekty rovny?
alert(objekt === kopieObjektu); // false (nenà to stejný odkaz)
// modifikace naÅ¡eho původnÃho objektu nezmÄnà kopii:
objekt.d = 4;
alert(JSON.stringify(objekt)); // {"a":1,"b":2,"c":3,"d":4}
alert(JSON.stringify(kopieObjektu)); // {"a":1,"b":2,"c":3}
Tento způsob kopÃrovánà objektu je mnohem kratšà než let kopieObjektu = Object.assign({}, objekt) nebo pro pole let kopiePole = Object.assign([], pole), takže mu dáváme pÅednost, kde jen můžeme.
ShrnutÃ
Když v kódu vidÃme "...", jsou to buÄ zbytkové parametry, nebo roztažená syntaxe.
Je možné mezi nimi snadno rozlišovat:
- Když je
...na konci funkÄnÃch parametrů, jsou to âzbytkové parametryâ a shromažÄujà zbytek seznamu argumentů do pole. - Když se
...vyskytuje ve volánà funkce nebo nÄÄem podobném, nazývá se âroztažená syntaxeâ a roztáhne pole do seznamu.
Vzory použitÃ:
- Zbytkové parametry se použÃvajà k vytváÅenà funkcÃ, které pÅijÃmajà libovolný poÄet argumentů.
- Roztažená syntaxe se použÃvá k pÅedánà pole do funkcÃ, které normálnÄ vyžadujà seznam mnoha argumentů.
SpoleÄnÄ nám pomáhajà snadno pÅepÃnat mezi seznamem a polem parametrů.
VÅ¡echny argumenty volánà funkce jsou rovnÄž k dispozici âve starém styluâ v objektu arguments: iterovatelném objektu podobném poli.
KomentáÅe
<code>, pro nÄkolik Åádků je obalte znaÄkou<pre>, pro vÃce než 10 Åádků vložte odkaz na pÃskoviÅ¡tÄ (plnkr, jsbin, codepenâ¦)