Opakovanie zberu údajov pomocou tradičných slučiek sa môže rýchlo stať ťažkopádnym a pomalým, najmä pri práci s obrovským množstvom údajov.
Generátory a iterátory JavaScriptu poskytujú riešenie na efektívnu iteráciu veľkých kolekcií údajov. Pomocou nich môžete riadiť tok iterácie, získavať hodnoty jednu po druhej a pozastaviť a obnoviť proces iterácie.
Tu pokryjete základy a interné prvky iterátora JavaScript a ako môžete vygenerovať iterátor manuálne a pomocou generátora.
Iterátory JavaScriptu
Iterátor je objekt JavaScript, ktorý implementuje protokol iterátora. Tieto objekty to robia tak, že majú a Ďalšie metóda. Táto metóda vráti objekt, ktorý implementuje IteratorResult rozhranie.
The IteratorResult rozhranie má dve vlastnosti: hotový a hodnotu. The hotový vlastnosť je boolovská hodnota, ktorá sa vracia falošný ak iterátor dokáže vyprodukovať ďalšiu hodnotu vo svojom poradí resp pravda ak iterátor dokončil svoju sekvenciu.
The hodnotu property je hodnota JavaScript vrátená iterátorom počas svojej sekvencie. Keď iterátor dokončí svoju sekvenciu (keď hotovýpravda), táto vlastnosť sa vráti nedefinované.
Ako už názov napovedá, iterátory vám umožňujú „iterovať“ cez objekty JavaScript, ako sú polia alebo mapy. Toto správanie je možné vďaka iterovateľnému protokolu.
V JavaScripte je iterovateľný protokol štandardným spôsobom definovania objektov, ktoré môžete iterovať, ako napr. pre...z slučka.
Napríklad:
konšt ovocie = ["banán", "Mango", "jablko", "hrozno"];
pre (konšt iterátor z ovocie) {
konzoly.log (iterátor);
}
/*
Banán
Mango
Apple
Hrozno
*/
Tento príklad iteruje cez ovocie pole pomocou a pre...z slučka. V každej iterácii zaznamená aktuálnu hodnotu do konzoly. Je to možné, pretože polia sú iterovateľné.
Niektoré typy JavaScriptu, ako sú polia, reťazce, Sady a mapy, sú vstavané iterovateľné, pretože oni (alebo jeden z objektov v ich prototypovom reťazci) implementujú an @@iterátor metóda.
Iné typy, ako napríklad objekty, nie sú štandardne iterovateľné.
Napríklad:
konšt iterObject = {
autá: ["Tesla", "BMW", "Toyota"],
zvierat: ["mačka", "Pes", "škrečok"],
jedlo: ["burgery", "pizza", "cestoviny"],
};pre (konšt iterátor z iterObject) {
konzoly.log (iterátor);
}
// TypeError: iterObject nemožno iterovať
Tento príklad ukazuje, čo sa stane, keď sa pokúsite iterovať objekt, ktorý nie je iterovateľný.
Vytvorenie iterovateľného objektu
Aby bol objekt iterovateľný, musíte implementovať a Symbol.iterátor metóda na objekte. Aby sa táto metóda stala iterovateľnou, musí vrátiť objekt, ktorý implementuje IteratorResult rozhranie.
The Symbol.iterátor symbol slúži na rovnaký účel ako @@iterátor a môžu byť zameniteľné v „špecifikácii“, ale nie v kóde ako @@iterátor nie je platná syntax JavaScript.
Nižšie uvedené bloky kódu poskytujú príklad toho, ako urobiť objekt iterovateľným pomocou iterObject.
Najprv pridajte Symbol.iterátor spôsob iterObject použitím funkciu vyhlásenie.
Ako:
iterObject[Symbol.iterátor] = funkciu () {
// Nasledujúce bloky kódu idú sem...
}
Ďalej budete potrebovať prístup ku všetkým kľúčom v objekte, ktorý chcete urobiť iterovateľným. Ku kľúčom sa dostanete pomocou Object.keys metóda, ktorá vracia pole vymenovateľných vlastností objektu. Ak chcete vrátiť pole iterObjectkľúče, odovzdajte toto kľúčové slovo ako argument Object.keys.
Napríklad:
nech objProperties = Objekt.keys(toto)
Prístup k tomuto poli vám umožní definovať iteračné správanie objektu.
Ďalej musíte sledovať iterácie objektu. Môžete to dosiahnuť pomocou premenných počítadla.
Napríklad:
nech propertyIndex = 0;
nech childIndex = 0;
Prvú premennú počítadla použijete na sledovanie vlastností objektu a druhú na sledovanie potomkov vlastnosti.
Ďalej budete musieť implementovať a vrátiť Ďalšie metóda.
Ako:
vrátiť {
Ďalšie() {
// Nasledujúce bloky kódu idú sem...
}
}
Vnútri Ďalšie budete musieť zvládnuť prípad okraja, ktorý nastane, keď bol celý objekt iterovaný. Aby ste zvládli okrajový prípad, musíte vrátiť predmet s hodnotu nastavený na nedefinované a hotový nastavený na pravda.
Ak sa tento prípad nevyrieši, pokus o iteráciu objektu bude mať za následok nekonečnú slučku.
Tu je postup, ako zvládnuť okrajový prípad:
ak (propertyIndex > objProperties.dĺžka- 1) {
vrátiť {
hodnota: nedefinované,
hotový: pravda,
};
}
Ďalej budete musieť získať prístup k vlastnostiam objektu a ich podriadeným prvkom pomocou premenných počítadla, ktoré ste deklarovali skôr.
Ako:
// Prístup k rodičovským a podradeným vlastnostiam
konšt vlastnosti = toto[objProperties[propertyIndex]];
konšt property = properties[childIndex];
Ďalej musíte implementovať nejakú logiku na zvýšenie premenných počítadla. Logika by mala resetovať childIndex keď v poli vlastnosti neexistujú žiadne ďalšie prvky a presuňte sa na ďalšiu vlastnosť v objekte. Okrem toho by sa mala zvýšiť childIndex, ak v poli aktuálnej vlastnosti stále existujú prvky.
Napríklad:
// Logika zvyšovania indexu
if (childIndex >= properties.length - 1) {
// ak v detskom poli nie sú žiadne ďalšie prvky
// resetovaťdieťaindex
childIndex = 0;
// Presun na ďalšiu vlastnosť
propertyIndex++;
} inak {
// Presun na ďalší prvok v detskom poli
childIndex++
}
Nakoniec vráťte predmet s hotový vlastnosť nastavená na falošný a hodnotu vlastnosť nastavená na aktuálny podradený prvok v iterácii.
Napríklad:
vrátiť {
hotový: falošný,
hodnota: majetok,
};
Vaše dokončené Symbol.iterátor funkcia by mala byť podobná bloku kódu nižšie:
iterObject[Symbol.iterátor] = funkciu () {
konšt objProperties = Objekt.keys(toto);
nech propertyIndex = 0;
nech childIndex = 0;vrátiť {
Ďalšie: () => {
//Manipulácia s okrajovým puzdrom
ak (propertyIndex > objProperties.dĺžka- 1) {
vrátiť {
hodnota: nedefinované,
hotový: pravda,
};
}// Prístup k rodičovským a podradeným vlastnostiam
konšt vlastnosti = toto[objProperties[propertyIndex]];
konšt property = properties[childIndex];// Logika zvyšovania indexu
if (childIndex >= properties.length - 1) {
// ak v detskom poli nie sú žiadne ďalšie prvky
// resetovaťdieťaindex
childIndex = 0;
// Presun na ďalšiu vlastnosť
propertyIndex++;
} inak {
// Presun na ďalší prvok v detskom poli
childIndex++
}
vrátiť {
hotový: falošný,
hodnota: majetok,
};
},
};
};
Beh a pre...z slučka zapnutá iterObject po tejto implementácii nevyvolá chybu, pretože implementuje a Symbol.iterátor metóda.
Ručná implementácia iterátorov, ako sme to urobili vyššie, sa neodporúča, pretože je veľmi náchylná na chyby a logika môže byť ťažko spravovateľná.
JavaScript generátory
Generátor JavaScriptu je funkcia, ktorej vykonávanie môžete kedykoľvek pozastaviť a obnoviť. Toto správanie mu umožňuje vytvárať postupnosť hodnôt v priebehu času.
Funkcia generátora, čo je funkcia, ktorá vracia generátor, poskytuje alternatívu k vytváraniu iterátorov.
Funkciu generátora môžete vytvoriť rovnakým spôsobom, ako by ste vytvorili deklaráciu funkcie v JavaScripte. Jediný rozdiel je v tom, že musíte pridať hviezdičku (*) na kľúčové slovo function.
Napríklad:
funkciu* príklad () {
vrátiť"Generátor"
}
Keď zavoláte normálnu funkciu v JavaScripte, vráti hodnotu určenú jej vrátiť kľúčové slovo resp nedefinované inak. Funkcia generátora však nevracia žiadnu hodnotu okamžite. Vracia objekt Generator, ktorý môžete priradiť k premennej.
Ak chcete získať prístup k aktuálnej hodnote iterátora, zavolajte na Ďalšie metóda na objekte Generátor.
Napríklad:
konšt gen = priklad();
console.log (gen.next()); // { hodnota: "Generátor", hotový: pravda }
Vo vyššie uvedenom príklade je hodnotu majetok pochádzal z a vrátiť kľúčové slovo, čím sa generátor efektívne ukončí. Toto správanie je pri funkciách generátora vo všeobecnosti nežiaduce, pretože to, čo ich odlišuje od bežných funkcií, je schopnosť pozastaviť a reštartovať vykonávanie.
Kľúčové slovo výnosu
The výnos Kľúčové slovo poskytuje spôsob iterácie hodnôt v generátoroch pozastavením vykonávania funkcie generátora a vrátením hodnoty, ktorá za ním nasleduje.
Napríklad:
funkciu* príklad() {
výnos"Model S"
výnos"Model X"
výnos"Kybernetický kamión"vrátiť"Tesla"
}konšt gen = priklad();
console.log (gen.next()); // { hodnota: 'Model S', hotový: falošný }
Vo vyššie uvedenom príklade, keď Ďalšie metóda sa volá na príklad generátor, zastaví sa vždy, keď narazí na výnos kľúčové slovo. The hotový majetok bude tiež nastavený na falošný kým nenarazí na a vrátiť kľúčové slovo.
Volanie na Ďalšie metóda viackrát na príklad generátor, aby ste to demonštrovali, budete mať ako výstup nasledujúce.
console.log (gen.next()); // { hodnota: "Model X", hotový: falošný }
console.log (gen.next()); // { hodnota: „kybernetické nákladné auto“, hotový: falošný }
console.log (gen.next()); // { hodnota: 'Tesla', hotový: pravda }
konzoly.log (gen.next()); // { hodnota: undefined, done: true }
Môžete tiež iterovať cez objekt generátora pomocou pre...z slučka.
Napríklad:
pre (konšt iterátor z gen) {
konzoly.log (iterátor);
}
/*
Model S
Model X
Cyber Truck
*/
Používanie iterátorov a generátorov
Hoci sa iterátory a generátory môžu zdať ako abstraktné pojmy, nie sú. Môžu byť užitočné pri práci s nekonečnými dátovými tokmi a kolekciami dát. Môžete ich použiť aj na vytvorenie jedinečných identifikátorov. Pod kapotou ich používajú aj knižnice štátneho manažmentu, ako je MobX-State-Tree (MST).