For-each over en matrise i JavaScript?
Hvordan kan jeg løkke gjennom alle oppføringene i en matrise ved hjelp av JavaScript?
Jeg trodde det var noe sånt som dette:
forEach(instance in theArray)
Hvor theArray
er matrisen min, men dette ser ut til å være feil.
4427
3
TL;DR
for-in
med mindre du bruker det med garantier eller i det minste er klar over hvorfor det kan bite deg.for-of
løkke (kun ES2015+),Array#forEach
([spec
][1] | [MDN
][2]) (eller dens slektningersome
og lignende) (kun ES5+),for
-sløyfe,eller
for-in
med sikkerhetstiltak. Men det er mye mer å utforske, les videre...JavaScript har kraftig semantikk for looping gjennom matriser og array-lignende objekter. Jeg har delt svaret i to deler: Alternativer for ekte arrays, og alternativer for ting som er bare array-like, for eksempel
arguments
objekt, andre iterable objekter (ES2015+), DOM samlinger, og så videre. Jeg vil raskt merke at du kan bruke ES2015-alternativene nå , selv på ES5-motorer, ved å overføre ES2015 til ES5. Søk etter "ES2015 transpiling" / "ES6 transpiling" for mer ... Ok, la oss se på alternativene våre:For faktiske matriser
Du har tre alternativer i [ECMAScript 5][3] ("ES5"), den versjonen som støttes mest for øyeblikket, og to til lagt til i [ECMAScript 2015][4] ("ES2015", "ES6"):
forEach
og relaterte (ES5+).for
-løkkefor-in
korrekt.for-of
(bruk en iterator implisitt) (ES2015+)1. Bruk
forEach
og relaterteI ethvert vagt moderne miljø (altså ikke IE8) der du har tilgang til
Array
-funksjonene som er lagt til av ES5 (direkte eller ved hjelp av polyfills), kan du brukeforEach
([spec
][1] | [MDN
][2]):forEach
aksepterer en tilbakeringingsfunksjon og eventuelt en verdi som skal brukes somthis
når tilbakeringingen kalles (ikke brukt ovenfor). Tilbakekallingen kalles for hver oppføring i matrisen, i rekkefølge, og hopper over ikke-eksisterende oppføringer i sparsomme matriser. Selv om jeg bare brukte ett argument ovenfor, kalles tilbakeringingen med tre: Verdien av hver oppføring, indeksen for den oppføringen, og en referanse til matrisen du itererer over (i tilfelle funksjonen din ikke allerede har den hendig). Med mindre du støtter foreldede nettlesere som IE8 (som NetApps viser til litt over 4% markedsandel i skrivende stund i september 2016), kan du gjerne brukeforEach
på en generell webside uten mellomlegg. Hvis du trenger å støtte foreldede nettlesere, er det enkelt å shimme/polyfilleforEach
(søk etter "es5 shim" for flere alternativer).forEach
har den fordelen at du ikke trenger å erklære indeksering og verdivariabler i det inneholdende omfanget, ettersom de leveres som argumenter til iterasjonsfunksjonen, og så pent avgrenset til bare den iterasjonen. Hvis du're bekymret for kjøretid kostnadene ved å gjøre et funksjonskall for hver array oppføring, ikke være; detaljer. I tillegg erforEach
funksjonen "loop through them all", men ES5 definerte flere andre nyttige "work your way through the array and do things" -funksjoner, inkludert:every
][5] (slutter å løkke første gang callback returnererfalse
eller noe falskt)some
][6] (slutter å løkke første gang tilbakekallingen returnerertrue
eller noe sant)filter
][7] (oppretter en ny matrise som inkluderer elementer der filterfunksjonen returnerertrue
og utelater de der den returnererfalse
)map
][8] (oppretter en ny matrise fra verdiene som returneres av tilbakekallingen)reduce
][9] (bygger opp en verdi ved gjentatte ganger å kalle tilbakekallingen og sende inn tidligere verdier; se spesifikasjonen for detaljer; nyttig for å summere innholdet i en matrise og mange andre ting)reduceRight
][10] (somreduce
, men fungerer i synkende i stedet for stigende rekkefølge)2. Bruk en enkel
for
løkkeNoen ganger er de gamle måtene de beste:
Hvis lengden på arrayet ikke endres i løpet av løkken, og det er i ytelsesfølsom kode (usannsynlig), kan en litt mer komplisert versjon som tar tak i lengden foran være litt raskere:
Og/eller teller baklengs:
Men med moderne JavaScript-motorer er det sjelden du trenger å hente ut den siste biten av juice. I ES2015 og nyere kan du gjøre indeks- og verdivariablene dine lokale for
for
-sløyfen:Og når du gjør det, blir ikke bare
value
, men ogsåindex
gjenskapt for hver loop-iterasjon, noe som betyr at lukninger opprettet i loop-kroppen holder en referanse tilindex
(ogvalue
) opprettet for den spesifikke iterasjonen:Hvis du hadde fem divs, ville du få "Index is: 0" hvis du klikket på den første og "Index is: 4 " hvis du klikket på den siste. Dette fungerer ikke hvis du bruker
var
i stedet forlet
.3. Bruk
for-in
korrekt.Du vil få folk til å be deg om å bruke
for-in
, men [det er ikke detfor-in
er til for][11].for-in
løkker gjennom de oppregnede egenskapene til et objekt, ikke indeksene til et array. Rekkefølgen er ikke garantert, ikke engang i ES2015 (ES6). ES2015+ definerer en rekkefølge for objektegenskaper (via[[OwnPropertyKeys]]
,[[Enumerate]]
, og ting som bruker dem som [Object.getOwnPropertyKeys
][12]), men den definerer ikke atfor-in
vil følge denne rekkefølgen. (Detaljer i [dette andre svaret][13]). De eneste virkelige brukstilfellene forfor-in
på en matrise er:for-in
for å besøke disse sparese array-elementene hvis du bruker passende sikkerhetstiltak:Bemerkning: Dette svaret er håpløst utdatert. For en mer moderne tilnærming, se metodene som er tilgjengelige på en matrise. Metoder av interesse kan være:
Standardmetoden for å iterere et array i JavaScript er en vanilje
for
-løkke:Merk imidlertid at denne tilnærmingen bare er bra hvis du har en tett matrise, og hver indeks er okkupert av et element. Hvis matrisen er sparsom, kan du støte på ytelsesproblemer med denne tilnærmingen, siden du vil iterere over mange indekser som ikke egentlig eksisterer i matrisen. I dette tilfellet kan en
for .. in
-løkke være en bedre idé. **Du må imidlertid bruke passende sikkerhetstiltak for å sikre at bare de ønskede egenskapene til matrisen (det vil si matriseelementene) blir behandlet, sidenfor..in
-løkken også vil bli oppregnet i eldre nettlesere, eller hvis tilleggsegenskapene er definert somenumerable
.I ECMAScript 5 vil det være en forEach-metode på array-prototypen, men den støttes ikke i eldre nettlesere. Så for å kunne bruke den konsekvent må du enten ha et miljø som støtter den (for eksempel Node.js for JavaScript på serversiden), eller bruke en "Polyfill". Polyfill for denne funksjonaliteten er imidlertid triviell, og siden den gjør koden lettere å lese, er det en god polyfill å inkludere.
Hvis du vil løkke over en matrise, bruker du standard tredelt
for
-løkke.Du kan få noen ytelsesoptimaliseringer ved å hurtigbufre
myArray.length
eller iterere over den bakover.