Tokie skaitytojai kaip jūs padeda palaikyti MUO. Kai perkate naudodami nuorodas mūsų svetainėje, galime uždirbti filialų komisinius. Skaityti daugiau.

Duomenų rinkimo kartojimas naudojant tradicines kilpas gali greitai tapti sudėtingas ir lėtas, ypač kai dirbama su didžiuliu duomenų kiekiu.

„JavaScript“ generatoriai ir iteratoriai yra sprendimas efektyviam didelių duomenų rinkinių iteravimui. Naudodami juos galite valdyti iteracijos srautą, gauti vertes po vieną ir pristabdyti bei tęsti iteracijos procesą.

Čia apžvelgsite „JavaScript“ iteratoriaus pagrindus ir vidinius dalykus bei kaip galite sugeneruoti iteratorių rankiniu būdu ir naudodami generatorių.

„JavaScript“ iteratoriai

Iteratorius yra „JavaScript“ objektas, įgyvendinantis iteratoriaus protokolą. Šie objektai tai daro turėdami a Kitas metodas. Šis metodas grąžina objektą, kuris įgyvendina Iteratoriaus rezultatas sąsaja.

The Iteratoriaus rezultatas sąsają sudaro dvi savybės: padaryta ir vertė. The padaryta nuosavybė yra loginė vertė, kuri grįžta

instagram viewer
klaidinga jei iteratorius gali sukurti kitą savo sekos reikšmę arba tiesa jei iteratorius baigė savo seką.

The vertė ypatybė yra „JavaScript“ reikšmė, kurią iteratorius grąžina savo sekos metu. Kai iteratorius užbaigia savo seką (kai padarytatiesa), ši nuosavybė grąžinama neapibrėžtas.

Kaip rodo pavadinimas, iteratoriai leidžia „iteruoti“ „JavaScript“ objektus, tokius kaip masyvai ar žemėlapiai. Toks elgesys įmanomas dėl kartojamo protokolo.

„JavaScript“ kartojamas protokolas yra standartinis būdas apibrėžti objektus, kuriuos galite kartoti, pvz., už...iš kilpa.

Pavyzdžiui:

konst vaisiai = ["Bananas", "Mango", "Apple", "Vynuogės"];

dėl (konst iteratorius apie vaisiai) {
konsolė.log (iteratorius);
}

/*
Bananas
Mango
Apple
Vynuogės
*/

Šis pavyzdys kartojasi per vaisiai masyvas naudojant a už...iš kilpa. Kiekvienoje iteracijoje dabartinė reikšmė įrašoma į konsolę. Tai įmanoma, nes masyvai yra kartojami.

Kai kurie JavaScript tipai, pvz., masyvai, eilutės, Rinkiniai ir žemėlapiai, yra įtaisytos kartotinės, nes jos (arba vienas iš objektų, esančių jų prototipų grandinėje) įgyvendina an @@iteratorius metodas.

Kiti tipai, pvz., objektai, pagal numatytuosius nustatymus nėra kartojami.

Pavyzdžiui:

konst iterObject = {
automobiliai: ["Tesla", "BMW", "Toyota"],
gyvūnai: ["Katė", "Šuo", "Žiurkėnas"],
maistas: ["Mėsainiai", "Pica", "Makaronai"],
};

dėl (konst iteratorius apie iterObject) {
konsolė.log (iteratorius);
}

// Tipo klaida: iterObject negalima kartoti

Šis pavyzdys parodo, kas nutinka, kai bandote kartoti objektą, kurio negalima kartoti.

Objekto pakeitimas

Norėdami, kad objektas būtų kartojamas, turite įdiegti a Simbolis.iteratorius metodas objekte. Kad būtų galima kartoti, šis metodas turi grąžinti objektą, kuris įgyvendina Iteratoriaus rezultatas sąsaja.

The Simbolis.iteratorius simbolis tarnauja tam pačiam tikslui kaip @@iteratorius ir gali būti naudojami pakaitomis „specifikacijoje“, bet ne kode kaip @@iteratorius neteisinga „JavaScript“ sintaksė.

Toliau pateiktuose kodo blokuose pateikiamas pavyzdys, kaip padaryti objektą kartojamą naudojant iterObject.

Pirmiausia pridėkite Simbolis.iteratorius metodas iterObject naudojant funkcija deklaracija.

Kaip taip:

iterObject[Simbolis.iteratorius] = funkcija () {
// Vėlesni kodo blokai eina čia...
}

Tada turėsite pasiekti visus raktus objekte, kurį norite pakartoti. Raktus galite pasiekti naudodami Objektas.raktai metodas, kuris grąžina nesuskaičiuojamų objekto savybių masyvą. Norėdami grąžinti masyvą iterObjectraktus, perduokite tai raktažodis kaip argumentas Objektas.raktai.

Pavyzdžiui:

leisti objProperties = Objektas.raktai(tai)

Prieiga prie šio masyvo leis apibrėžti objekto iteracijos elgesį.

Tada turite sekti objekto iteracijas. Tai galite pasiekti naudodami skaitiklio kintamuosius.

Pavyzdžiui:

leisti propertyIndex = 0;
leisti vaikasIndeksas = 0;

Pirmąjį skaitiklio kintamąjį naudosite objekto savybėms stebėti, o antrąjį – nuosavybės antriniams rodikliams.

Tada turėsite įdiegti ir grąžinti Kitas metodas.

Kaip taip:

grąžinti {
Kitas() {
// Vėlesni kodo blokai eina čia...
}
}

Viduje Kitas metodą, turėsite tvarkyti krašto atvejį, kuris atsiranda, kai visas objektas buvo kartojamas. Norėdami tvarkyti kraštinį atvejį, turite grąžinti objektą su vertė nustatytas į neapibrėžtas ir padaryta nustatytas į tiesa.

Jei šis atvejis nebus tvarkomas, bandant kartoti objektą, atsiras begalinis ciklas.

Štai kaip tvarkyti krašto dėklą:

jeigu (propertyIndex > objYpatybės.ilgis- 1) {
grąžinti {
vertė: neapibrėžtas,
padaryta: tiesa,
};
}

Tada turėsite pasiekti objekto ypatybes ir jų antrinius elementus naudodami anksčiau deklaruotus skaitiklio kintamuosius.

Kaip taip:

// Prieiga prie tėvų ir antrinių savybių
konst savybės = tai[objProperties[propertyIndex]];

konst nuosavybė = savybės[vaikoIndeksas];

Tada turite įdiegti tam tikrą skaitiklio kintamųjų didinimo logiką. Logika turėtų iš naujo nustatyti vaikasIndeksas kai nuosavybės masyve daugiau elementų nėra ir pereinama prie kitos objekto savybės. Be to, jis turėtų padidėti vaikasIndeksas, jei dabartinės nuosavybės masyve vis dar yra elementų.

Pavyzdžiui:

// Indekso didinimo logika
if (childIndex >= savybės.ilgis – 1) {
// jei antriniame masyve nebėra elementų
// nustatyti iš naujovaikasindeksas
vaikasIndeksas = 0;

// Perkelti į kitą nuosavybę
propertyIndex++;
} Kitas {
// Pereiti prie kito elemento antriniame masyve
vaikasIndex++
}

Galiausiai grąžinkite objektą su padaryta nustatyta nuosavybė klaidinga ir vertė ypatybė nustatyta kaip dabartinis antrinis iteracijos elementas.

Pavyzdžiui:

grąžinti {
padaryta: klaidinga,
vertė: turtas,
};

Jūs baigėte Simbolis.iteratorius funkcija turėtų būti panaši į toliau pateiktą kodo bloką:

iterObject[Simbolis.iteratorius] = funkcija () {
konst objProperties = Objektas.raktai(tai);
leisti propertyIndex = 0;
leisti vaikasIndeksas = 0;

grąžinti {
Kitas: () => {
//Krašto atvejo tvarkymas
jeigu (propertyIndex > objYpatybės.ilgis- 1) {
grąžinti {
vertė: neapibrėžtas,
padaryta: tiesa,
};
}

// Prieiga prie tėvų ir antrinių savybių
konst savybės = tai[objProperties[propertyIndex]];

konst nuosavybė = savybės[vaikoIndeksas];

// Indekso didinimo logika
if (childIndex >= savybės.ilgis – 1) {
// jei antriniame masyve nebėra elementų
// nustatyti iš naujovaikasindeksas
vaikasIndeksas = 0;

// Perkelti į kitą nuosavybę
propertyIndex++;
} Kitas {
// Pereiti prie kito elemento antriniame masyve
vaikasIndex++
}

grąžinti {
padaryta: klaidinga,
vertė: turtas,
};
},
};
};

Bėgimas a už...iš kilpa įjungta iterObject po šio įgyvendinimo nepadarys klaidos, nes įgyvendina a Simbolis.iteratorius metodas.

Rankiniu būdu diegti iteratorius, kaip darėme aukščiau, nerekomenduojama, nes jame labai daug klaidų, o logiką gali būti sunku valdyti.

JavaScript generatoriai

„JavaScript“ generatorius yra funkcija, kurios vykdymą galite pristabdyti ir atnaujinti bet kuriuo metu. Toks elgesys leidžia laikui bėgant sukurti verčių seką.

Generatoriaus funkcija, kuri yra funkcija, kuri grąžina generatorių, yra alternatyva iteratorių kūrimui.

Galite sukurti generatoriaus funkciją taip pat, kaip kurtumėte funkcijos deklaraciją „JavaScript“. Vienintelis skirtumas yra tas, kad turite pridėti žvaigždutę (*) į funkcijos raktinį žodį.

Pavyzdžiui:

funkcija* pavyzdys () {
grąžinti"Generatorius"
}

Kai iškviečiate įprastą funkciją „JavaScript“, ji grąžina jos nurodytą reikšmę grąžinti raktažodis arba neapibrėžtas kitaip. Tačiau generatoriaus funkcija negrąžina jokios reikšmės iš karto. Jis grąžina generatoriaus objektą, kurį galite priskirti kintamajam.

Norėdami pasiekti dabartinę iteratoriaus reikšmę, skambinkite Kitas metodą generatoriaus objekte.

Pavyzdžiui:

konst gen = pavyzdys();

console.log (gen.next()); // { reikšmė: "Generatorius", padaryta: tiesa }

Aukščiau pateiktame pavyzdyje vertė turtas atkeliavo iš a grąžinti raktažodį, efektyviai nutraukdamas generatorių. Šis elgesys paprastai yra nepageidautinas naudojant generatoriaus funkcijas, nes tai, kas jas skiria nuo įprastų funkcijų, yra galimybė pristabdyti ir iš naujo paleisti vykdymą.

Derliaus raktinis žodis

The derlius raktinis žodis suteikia galimybę kartoti reikšmes generatoriuose pristabdant generatoriaus funkcijos vykdymą ir grąžinant po jos esančią reikšmę.

Pavyzdžiui:

funkcija* pavyzdys() {
derlius„S modelis“
derlius"Modelis X"
derlius„Kibernetinis sunkvežimis“

grąžinti"Tesla"
}

konst gen = pavyzdys();

console.log (gen.next()); // { reikšmė: "Model S", padaryta: klaidinga }

Aukščiau pateiktame pavyzdyje, kai Kitas metodas iškviečiamas pavyzdys generatorius, jis bus pristabdytas kiekvieną kartą, kai susidurs su derlius raktažodį. The padaryta nuosavybė taip pat bus nustatyta klaidinga kol susidurs su a grąžinti raktažodį.

Skambindamas į Kitas metodas kelis kartus pavyzdys generatorius, kad tai parodytų, turėsite toliau nurodytą išvestį.

console.log (gen.next()); // { reikšmė: "Modelis X", padaryta: klaidinga }
console.log (gen.next()); // { reikšmė: "Kibernetinis sunkvežimis", padaryta: klaidinga }
console.log (gen.next()); // { reikšmė: "Tesla", padaryta: tiesa }

konsolė.log (gen.next()); // { vertė: neapibrėžta, atlikta: tiesa }

Taip pat galite kartoti per generatoriaus objektą naudodami už...iš kilpa.

Pavyzdžiui:

dėl (konst iteratorius apie gen) {
konsolė.log (iteratorius);
}

/*
Modelis S
X modelis
Kibernetinis sunkvežimis
*/

Iteratorių ir generatorių naudojimas

Nors iteratoriai ir generatoriai gali atrodyti kaip abstrakčios sąvokos, taip nėra. Jie gali būti naudingi dirbant su begaliniais duomenų srautais ir duomenų rinkiniais. Taip pat galite juos naudoti kurdami unikalius identifikatorius. Valstybės valdymo bibliotekos, tokios kaip MobX-State-Tree (MST), taip pat naudoja jas po gaubtu.