Viac na
For-each nad poľom v JavaScripte?
Ako môžem prechádzať všetky položky v poli pomocou jazyka JavaScript?
Myslel som, že je to niečo také:
forEach(instance in theArray)
Kde theArray
je moje pole, ale zdá sa, že to nie je správne.
4427
3
TL;DR
for-in
, pokiaľ ho nepoužívate s ochrannými opatreniami alebo si aspoň nie ste vedomí, prečo by vás to mohlo štípať.for-of
(len ES2015+),Array#forEach
([spec
][1] | [MDN
][2]) (alebo jeho príbuznésome
a podobne) (iba ES5+),for
,alebo
for-in
s ochrannými prvkami. Ale je toho oveľa viac, čo môžete preskúmať, čítajte ďalej...JavaScript má výkonnú sémantiku pre cykly cez polia a objekty podobné poliam. Odpoveď som'rozdelil na dve časti: Možnosti pre skutočné polia a možnosti pre veci, ktoré sú len poliampodobné, ako napríklad objekt
argumenty
, iné iterovateľné objekty (ES2015+), kolekcie DOM atď. Rýchlo poznamenám, že možnosti ES2015 môžete používať už teraz, dokonca aj na motoroch ES5, a to transpiláciou* ES2015 do ES5. Vyhľadajte "ES2015 transpiling" / "ES6 transpiling" pre viac informácií... Dobre, pozrime sa na naše možnosti:Pre skutočné polia
Máte tri možnosti v [ECMAScript 5][3] ("ES5"), v súčasnosti najširšie podporovanej verzii, a ďalšie dve pridané v [ECMAScript 2015][4] ("ES2015", "ES6"):
forEach
a súvisiacich (ES5+)for
for-in
správnefor-of
(implicitne použite iterátor) (ES2015+)1. Používajte
forEach
a súvisiaceV každom nejasne modernom prostredí (teda nie v IE8), kde máte prístup k funkciám
Array
pridaným v ES5 (priamo alebo pomocou polyfillov), môžete použiťforEach
([spec
][1] | [MDN
][2]): -- begin snippet: js hide: false console: true babel: false -->forEach
akceptuje funkciu spätného volania a voliteľne hodnotu, ktorá sa použije akothis
pri volaní tohto spätného volania (vyššie nepoužité). Spätné volanie sa zavolá pre každú položku v poli v poradí, pričom sa preskočia neexistujúce položky v riedkych poliach. Hoci som vyššie použil len jeden argument, spätné volanie sa volá s tromi: Hodnota každej položky, index tejto položky a odkaz na pole, ktoré iterujete (v prípade, že ho vaša funkcia ešte nemá po ruke). Pokiaľ'nepodporujete zastarané prehliadače, ako je IE8 (ktorého trhový podiel podľa údajov spoločnosti NetApps v čase písania tohto článku v septembri 2016 bol len niečo vyše 4 %), môžeteforEach
spokojne používať na univerzálnej webovej stránke bez shimu. Ak potrebujete podporovať zastarané prehliadače, shimming/polyfillingforEach
sa dá ľahko vykonať (vyhľadajte "es5 shim" pre niekoľko možností).forEach
má tú výhodu, že nemusíte deklarovať indexovacie a hodnotové premenné v obsahujúcom obore, pretože sú dodávané ako argumenty iteračnej funkcie, a tak sú pekne zakreslené len na túto iteráciu. Ak sa obávate nákladov na vykonávanie funkcie pre každú položku poľa, nemusíte; podrobnosti. Okrem toho jeforEach
funkcia "loop through them all", ale ES5 definovala niekoľko ďalších užitočných "work your way through the array and do things" funkcií, vrátane:every
][5] (zastaví cyklus pri prvom vrátenífalse
alebo niečoho chybného)some
][6] (zastaví cyklus, keď spätné volanie vráti prvýkráttrue
alebo niečo pravdivé)filter
][7] (vytvorí nové pole obsahujúce prvky, pri ktorých funkcia filter vrátipravdivé
a vynechá tie, pri ktorých vrátinepravdivé
)map
][8] (vytvorí nové pole z hodnôt vrátených spätným volaním)reduce
][9] (vytvorí hodnotu opakovaným volaním spätného volania, pričom odovzdá predchádzajúce hodnoty; podrobnosti nájdete v špecifikácii; užitočné na sčítanie obsahu poľa a mnoho ďalších vecí)reduceRight
][10] (akoreduce
, ale pracuje v zostupnom, nie vzostupnom poradí)2. Použite jednoduchý cyklus
for
Niekedy sú staré spôsoby najlepšie:
Ak sa dĺžka poľa nebude počas cyklu meniť a je to v kóde citlivom na výkon (nepravdepodobné), trochu komplikovanejšia verzia, ktorá chytá dĺžku vopred, by mohla byť tiny trochu rýchlejšia:
A/alebo spätné počítanie:
V moderných JavaScriptových enginoch však len zriedkakedy potrebujete vyžmýkať posledný kúsok šťavy. V ES2015 a vyšších verziách môžete premenné index a hodnota urobiť lokálnymi v cykle
for
:A keď to urobíte, nielen
value
, ale ajindex
sa znovu vytvorí pre každú iteráciu cyklu, čo znamená, že uzávery vytvorené v tele cyklu si zachovajú odkaz naindex
(avalue
) vytvorený pre danú iteráciu:Ak by ste mali päť divov, dostali by ste "Index is: 0" ak by ste klikli na prvý a "Index je: 4" ak by ste klikli na posledný. Toto nefunguje, ak použijete
var
namiestolet
.3. Používajte
for-in
správneĽudia vám budú hovoriť, aby ste používali
for-in
, ale [na tofor-in
neslúži][11].for-in
prechádza cez vypočítateľné vlastnosti objektu, nie cez indexy poľa. Poradie nie je zaručené, dokonca ani v ES2015 (ES6). ES2015+ síce definuje poradie vlastností objektu (prostredníctvom[[OwnPropertyKeys]]
,[[Enumerate]]
a vecí, ktoré ich používajú, ako napríklad [Object.getOwnPropertyKeys
][12]), ale nedefinuje, žefor-in
bude toto poradie dodržiavať. (Podrobnosti v [tejto inej odpovedi][13].) Jediné skutočné prípady použitiafor-in
na poli sú:for-in
na navštívenie týchto voľných prvkov poľa:Poznámka: Táto odpoveď je beznádejne zastaraná. Modernejší prístup nájdete na stránke metódy dostupné na poli. Zaujímavé metódy by mohli byť:
Štandardný spôsob iterácie poľa v JavaScripte je jednoduchá slučka
for
:Všimnite si však, že tento prístup je dobrý len vtedy, ak máte husté pole a každý index je obsadený prvkom. Ak je pole riedke, potom môžete pri tomto prístupe naraziť na výkonnostné problémy, pretože budete iterovať cez množstvo indexov, ktoré v poli skutočne neexistujú. V takom prípade môže byť lepším nápadom slučka
for .. in
. **Musíte však použiť vhodné ochranné opatrenia, aby ste zabezpečili, že sa bude konať len s požadovanými vlastnosťami poľa (t. j. s prvkami poľa), pretože slučkafor ...in
bude v starších prehliadačoch aj enumerovaná, alebo ak sú dodatočné vlastnosti definované akoenumerovateľné
.V ECMAScripte 5 bude na prototype poľa metóda forEach, ktorá však nie je podporovaná v starších prehliadačoch. Aby ste ju teda mohli dôsledne používať, musíte mať buď prostredie, ktoré ju podporuje (napríklad Node.js pre JavaScript na strane servera), alebo použiť "Polyfill". Polyfill pre túto funkcionalitu je však triviálny a keďže uľahčuje čítanie kódu, je dobré ho zahrnúť.
Ak chcete vytvoriť cyklus nad poľom, použite štandardný trojdielny cyklus
for
.Niektoré optimalizácie výkonu môžete dosiahnuť ukladaním
myArray.length
do vyrovnávacej pamäte alebo spätným iterovaním.