Daugiau
For-each per masyvą "JavaScript"?
Kaip, naudojant "JavaScript", pervesti ciklą per visus masyvo įrašus?
Maniau, kad tai yra kažkas panašaus:
forEach(instance in theArray)
kur theArray
yra mano masyvas, bet atrodo, kad tai neteisinga.
4427
3
TL;DR
for-in
, jei nenaudojate jo su apsaugos priemonėmis arba bent jau nežinote, kodėl jis gali jums įgristi.for-of
ciklas (tik ES2015+),Array#forEach
([spec
][1] | [MDN
][2]) (arba jo giminaičiaisome
ir panašūs) (tik ES5+),for
ciklas,arba
for-in
su apsaugos priemonėmis. Tačiau yra dar daugybė dalykų, kuriuos galima ištirti, skaitykite toliau..."JavaScript" turi galingą ciklo per masyvus ir į masyvus panašius objektus semantiką. Atsakymą padalinau į dvi dalis: Tikrųjų masyvų parinktis ir į masyvus panašių dalykų, pavyzdžiui, objekto
arguments
, kitų iteruojamų objektų (ES2015+), DOM kolekcijų ir t. t., parinktis. Greitai pažymėsiu, kad ES2015 parinktis galite naudoti nuo šiol, net ES5 varikliuose, transpiliavę ES2015 į ES5. Ieškokite "ES2015 transpiling" / "ES6 transpiling", kad sužinotumėte daugiau... Gerai, apžvelkime savo galimybes:Faktiniams masyvams
[ECMAScript 5][3] ("ES5"), šiuo metu plačiausiai palaikomoje versijoje, turite tris parinktis, o [ECMAScript 2015][4] ("ES2015", "ES6") pridėtos dar dvi ("ES2015", "ES6"):
forEach
ir susijusius (ES5+)for
cikląfor-in
korektiškaifor-of
(netiesiogiai naudokite iteratorių) (ES2015+)1. Naudokite
forEach
ir susijusiusBet kokioje neaiškios šiuolaikinės technologijos aplinkoje (taigi, ne IE8), kurioje turite prieigą prie ES5 pridėtų
Array
funkcijų (tiesiogiai arba naudodami polipinius papildymus), galite naudotiforEach
([spec
][1] | [MDN
][2]):forEach
priima grįžtamojo ryšio funkciją ir, pasirinktinai, reikšmę, kuri bus naudojama kaipthis
, kai bus kviečiamas šis grįžtamasis ryšys (pirmiau nenaudota). Grįžtamasis skambutis kviečiamas kiekvienam masyvo įrašui eilės tvarka, praleidžiant neegzistuojančius įrašus retuose masyvuose. Nors pirmiau naudojau tik vieną argumentą, grįžtamasis skambutis kviečiamas su trimis argumentais: kiekvieno įrašo vertė, to įrašo indeksas ir nuoroda į masyvą, kurį iteruojate (jei jūsų funkcija dar neturi jos po ranka). Jei nepalaikysite pasenusių naršyklių, tokių kaip IE8 (NetApps rodo, kad jos rinkos dalis šio rašinio rašymo metu, 2016 m. rugsėjį buvo vos daugiau nei 4 %),forEach
bendrojo naudojimo tinklalapyje galite drąsiai naudoti be shim'o. Jei jums reikia palaikyti pasenusias naršykles, nesunkiai galima atliktiforEach
shimming/polyfilling (ieškokite "es5 shim" kelių parinkčių).forEach
privalumas yra tas, kad jums nereikia deklaruoti indeksavimo ir vertės kintamųjų turinčioje srityje, nes jie pateikiami kaip iteracijos funkcijos argumentai, todėl yra gražiai pritaikyti tik tai iteracijai. Jei nerimaujate, kad dėl kiekvieno masyvo įrašo teks atlikti funkcijos iškvietimą, nesijaudinkite; informacija. Be to,forEach
yra "ciklo per juos visus" funkcija, tačiau ES5 apibrėžė keletą kitų naudingų "pereikite per masyvą ir atlikite veiksmus" funkcijų, pvz:every
][5] (nutraukia ciklą, kai pirmą kartą grįžtamasis skambutis grąžinafalse
arba ką nors klaidingo)some
][6] (sustabdo ciklą pirmą kartą, kai grįžtamasis skambutis grąžinatrue
arba ką nors teisingo)filter
][7] (sukuria naują masyvą, į kurį įtraukiami elementai, kai filtravimo funkcija grąžinateisingą
, ir praleidžiami elementai, kai ji grąžinaneteisingą
)map
][8] (sukuria naują masyvą iš reikšmių, kurias grąžino grįžtamasis skambutis)reduce
][9] (sukuria vertę pakartotinai skambindama atgaliniam skambučiui ir perduodama ankstesnes vertes; išsamią informaciją žr. specifikacijoje; naudinga sumuojant masyvo turinį ir daugeliui kitų dalykų)reduceRight
][10] (kaip irreduce
, bet veikia mažėjimo, o ne didėjimo tvarka)2. Naudokite paprastą
for
cikląKartais seni būdai yra geriausi:
Jei ciklo metu masyvo ilgis nesikeis ir tai yra našumui jautrus kodas (mažai tikėtina), šiek tiek sudėtingesnis variantas, kai ilgis nustatomas iš anksto, gali būti šiek tiek greitesnis:
Ir/arba skaičiuojant atgal:
Tačiau su šiuolaikiniais JavaScript varikliais retai kada prireikia išgauti tą paskutinį sulčių kiekį. ES2015 ir naujesnėse versijose galite padaryti savo indekso ir reikšmės kintamuosius vietiniais
for
ciklo kintamaisiais:Kai tai darote, ne tik
value
, bet irindex
iš naujo sukuriama kiekvienai ciklo iteracijai, t. y. ciklo kūne sukurtos uždaromosios struktūros išlaiko nuorodą į konkrečiai iteracijai sukurtąindex
(irvalue
):Jei turėtumėte penkis divus, gautumėte "Index is: 0", jei spustelėtumėte pirmąją ir "Index is: Jei spustelėjote paskutinįjį, būtų: &" 4". Tai neveikia, jei vietoj
let
naudojatevar
.3. Naudokite
for-in
tinkamaiJums' žmonės lieps naudoti
for-in
, betfor-in
skirtas ne tam, kad būtų galima jį naudoti [11].for-in
sudaro ciklą per objekto išskaičiuojamas savybes, o ne per masyvo indeksus. Tokia tvarka negarantuojama net ES2015 (ES6). ES2015+ apibrėžia objektų savybių eiliškumą (per[[OwnPropertyKeys]]
,[[Enumerate]]
ir juos naudojančius dalykus, pavyzdžiui, [Object.getOwnPropertyKeys
][12]), tačiau neapibrėžia, kadfor-in
laikysis šio eiliškumo. (Išsamiau [šiame kitame atsakyme][13].) Vieninteliai realūsfor-in
naudojimo atvejai masyve yra šie:for-in
, kad aplankytumėte tuos retus masyvo elementus, jei naudojate tinkamas apsaugos priemones:Pastaba: Šis atsakymas yra beviltiškai pasenęs. Šiuolaikiškesnio požiūrio ieškokite metodai, kuriais galima naudotis masyvu. Įdomūs metodai gali būti šie:
Standartinis būdas iteruoti masyvą JavaScript kalba yra "vanilinė"
for
kilpa:Tačiau atkreipkite dėmesį, kad šis metodas tinka tik tada, jei masyvas yra tankus ir kiekvienas indeksas yra užimtas elemento. Jei masyvas yra retas, taikant šį metodą gali kilti našumo problemų, nes bus iteruojama per daug indeksų, kurių iš tikrųjų nėra masyve. Tokiu atveju geresnė idėja būtų
for .. in
ciklas. Tačiau turite naudoti atitinkamas apsaugos priemones, kad užtikrintumėte, jog bus veikiama tik su norimomis masyvo savybėmis (t. y. su masyvo elementais), nesfor...in
ciklas taip pat bus skaičiuojamas senesnėse naršyklėse arba jei papildomos savybės apibrėžtos kaipenumerable
.ECMAScript 5 bus sukurtas masyvo prototipo forEach metodas, tačiau senosiose naršyklėse jis nepalaikomas. Taigi, norėdami nuosekliai jį naudoti, turite turėti aplinką, kuri jį palaiko (pavyzdžiui, Node.js serverio pusės JavaScript), arba naudoti "Polyfill". Tačiau šios funkcijos polistilius yra trivialus, o kadangi jis palengvina kodo skaitymą, jį verta įtraukti.
Jei norite cikliškai peržiūrėti masyvą, naudokite standartinį trijų dalių ciklą
for
.Galite šiek tiek optimizuoti našumą spartindami
myArray.length
arba iteruodami per jį atgal.