Mai mult
Pentru-fiecare pe o matrice în JavaScript?
Cum pot buclă prin toate intrările într-o matrice folosind JavaScript?
Am crezut că a fost ceva de genul:
forEach(instance in theArray)
Unde theArray` este matricea mea, dar acest lucru pare a fi incorecte.
4427
33
TL;DR
de-in
dacă nu-l utilizați cu garanții sau sunt măcar conștienți de ce s-ar putea să te muște.Matrice#forEach
([spec
][1] | [MDN
][2]) (sau rudele sale "unele" și astfel) (ES5+ numai),sau
de-in
cu garanții. Dar nu's *o mulțime *** mai mult pentru a explora, citiți mai departe...JavaScript are puternice semantica pentru looping prin tablouri și matrice ca obiecte. Am'am împărțit răspunsul în două părți: Opțiuni pentru veritabilă matrice, și opțiuni pentru lucruri care sunt doar array-ca, cum ar fi "argumente" de obiect, alte iterable obiecte (ES2015+), DOM colecții, și așa mai departe. Am'll rapid rețineți că puteți utiliza ES2015 opțiuni acum, chiar pe ES5 motoare, de transpiling ES2015 să ES5. Căutare pentru "ES2015 transpiling" / "ES6 transpiling" pentru mai multe... Bine, las's se uite la opțiunile noastre:
Pentru Matrice Reale
Ai trei opțiuni în [ECMAScript 5][3] ("ES5"), versiunea cea mai larg acceptată în momentul de față, și două mai adăugat în [ECMAScript 2015][4] ("ES2015", "ES6"):
de-in
corectde-a
(foloseste un iterator implicit) (ES2015+)1. Utilizarea "forEach" și conexe
În orice vag-mediu modern (deci, nu IE8) în cazul în care aveți acces la "Matrice" caracteristici adăugate de către ES5 (direct sau folosind polyfills), puteți folosi "forEach" ([
spec
][1] | [MDN
][2]):"forEach" acceptă o funcție de apel invers și, opțional, o valoare a folosi ca "asta", atunci când apel ca apel invers (nu sunt folosite de mai sus). Callback este apelată pentru fiecare intrare în serie, în ordine, sărind peste inexistente intrări în tablouri rare. Deși am folosit doar un singur argument de mai sus, callback este apelată cu trei: valoarea de fiecare intrare, indicele de intrare, și o referire la matricea're iterarea peste (în cazul în care funcția nu't au deja la îndemână). Dacă nu're sprijinirea învechite browsere, cum ar fi IE8 (care NetApps prezinta la peste 4% cota de piață ca din acest scris, în septembrie 2016), puteți folosi fericit "forEach" în general-scop, o pagină web fără un shim. Dacă aveți nevoie pentru a sprijini învechite browsere, shimming/polyfilling "forEach" este foarte usor de facut (de căutare pentru "es5 shim" pentru mai multe opțiuni). "forEach" are avantajul că nu't trebuie să declare indexare și valoarea variabile în conținut de aplicare, cum se're furnizate ca argumente la funcția de repetare, și atât de frumos luneta doar ca repetare. Daca're îngrijorat de execuție costul de a face un apel de funcție pentru fiecare vector de intrare, don't fi; detalii. În plus, "forEach" este "bucla prin-le pe toate" funcție, dar ES5 definite mai multe alte utile "locul de muncă-ți de drum prin matrice și de a face lucruri" funcții, inclusiv:
fiecare
][5] (se oprește looping prima dată callback returneaza "false" sau ceva falsey)ceva
][6] (se oprește looping prima dată apel invers returnează "adevărat" sau ceva sinceră)filtru
][7] (creează o nouă matrice, inclusiv elemente în cazul în care filtrul funcția returnează "adevărat" și omițând cele în care se întoarce "false")harta
][8] (creează o nouă matrice de valori returnate de apel invers)reduce
][9] (se acumulează o valoare de care apelează în mod repetat apel invers, trecerea de la valorile anterioare; vezi spec pentru detalii; util pentru însumarea cuprins de o matrice și multe alte lucruri)reduceRight
][10] (cum ar fi "reduce", dar funcționează în ordine descrescătoare, mai degrabă decât ordine crescătoare)2. Folosiți un simplu "pentru" bucla
Uneori metodele vechi sunt cele mai bune:
Dacă lungimea de matrice a câștigat't schimba în buclă, și-l's de performanță sensibile cod (puțin probabil), un pic mai complicat versiune hapsân lungimea în față ar putea fi o mica mai repede:
Și/sau numărare înapoi:
Dar cu moderne JavaScript motoare, l's rare aveți nevoie să prelungim ultimul pic de suc. În ES2015 și mai mare, puteți face index și valoare variabile locale la "pentru" bucla:
Și când faci asta, nu doar "valoare", dar, de asemenea, "index" este recreat pentru fiecare buclă iterație, în sensul de închidere a creat în corpul buclei să păstreze o referință la "index" (și "valoare") creat pentru o anumită iterație:
Dacă ai avut cinci divs, ai'd a obține "Indicele este: 0" dacă ați făcut clic pe primul și "Indicele este: 4" dacă ați făcut clic pe ultimul. Acest lucru nu funcționa dacă utilizați var
în loc de
lasa`.3. Utilizarea
de-in
corectTe'll a obține oameni spunându-vă să utilizați
de-in
, dar [că's nu cede-in
pentru][11].de-in
bucle prin nenumărate proprietăți a unui obiect, nu indici de o matrice. Ordinea nu este garantat, nu chiar în ES2015 (ES6). ES2015+ definește un ordin de proprietăți obiect (prin[[OwnPropertyKeys]]
,[[Enumerate]]
și lucrurile pe care le utilizați, cum ar fi [de Obiect.getOwnPropertyKeys
][12]), dar nu nu definirea căde-in
vor urma ordinea asta. (Detalii în [acest alt răspuns][13].) Singurele cazuri de utilizare pentrude-in
pe o matrice sunt:de-in
pentru a vizita acele sparese elementele de matrice dacă utilizați garanții corespunzătoare:Notă: Acest răspuns este iremediabil out-of-data. Pentru o abordare mai modernă, uita-te la metodele disponibile pe o serie. Metodele de interes ar putea fi:
Modul standard de a repeta o matrice în JavaScript este o vanilie "pentru" -bucla:
Rețineți, totuși, că această abordare este bună doar dacă ai o matrice densa, și fiecare indice este ocupat de un element. Dacă o matrice este rară, atunci puteți rula în probleme de performanță cu această abordare, deoarece va repeta peste o mulțime de indici care nu într-adevăr există în matrice. În acest caz, pentru .. în buclă ar putea fi o idee mai bună. Cu toate acestea**, trebuie să utilizați garanții adecvate pentru a se asigura că numai proprietățile dorite de matrice (care este, elementele de matrice) au acționat, încă din anii
pentru..în buclă va fi, de asemenea, enumerate în moștenirea browsere, sau daca proprietăți suplimentare sunt definite ca
enumerable`.În ECMAScript 5 nu va fi un forEach metoda pe matrice de prototip, dar acesta nu este acceptat în moștenirea browsere. Deci, pentru a fi capabil să-l folosească în mod constant trebuie să fie un mediu care acceptă (de exemplu, Node.js pentru server side JavaScript), sau de a folosi un "Polyfill". La Polyfill pentru această funcționalitate este, cu toate acestea, banal și de a face codul mai ușor de citit, este un bun polyfill pentru a include.
Dacă utilizați jQuery, bibliotecă, puteți utiliza jQuery.fiecare:
EDIT :
După fiecare întrebare, utilizatorul vrea cod în javascript în loc de jquery atât de editare este
Buclă înapoi
Cred că invers pentru bucla merită o mențiune aici:
Avantaje:
forEach()
și să ES6'spentru ... de
.Dezavantaje:
În buclă inversă este confuz pentru dezvoltatorii de juniori. (Vei considera asta un avantaj, în funcție de outlook.)
În cazul în care am folosi întotdeauna?
Unii dezvoltatori utilizarea inversă pentru buclă implicit, dacă nu există un motiv bun pentru a bucla înainte. Deși câștiguri de performanță sunt de obicei nesemnificative, este un fel de țipete:
pentru
șiîn timp ce
bucle).Acum este chiar mai bine să utilizați pentru..a!
Există o dezbatere cu privire la posibilitatea
pentru..a " sau " forEach()
sunt de preferat:Și în plus
așteaptă
nu funcționează în interiorulforEach()
. Folosind pentru..aeste [cel mai clar model](https://github.com/airbnb/javascript/issues/1122#issuecomment-259876436) în acest caz. Personal, am tendința de a folosi orice pare mai simplu de a citi, dacă nu de performanță sau de minimizare a devenit o preocupare majoră. Deci, în aceste zile eu prefer să folosesc pentru..a "în loc de" forEach()
, dar nu va folosi întotdeauna "hartă" sau "filtru" sau ["găsi"] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) sauceva
atunci când este cazul. (De dragul de colegii mei, eu folosesc rarreduce
.)Cum funcționează?
Veți observa că
i -
este mijlocul clauze (în cazul în care vom vedea, de obicei, o comparație) și ultima propoziție este gol (în cazul în care vom vedea, de obicei,i++
). Asta înseamnă căi -
este, de asemenea, utilizat ca stare pentru continuare. În mod esențial, este executată și verificată înainte fiecare iterație.i -
ruleaza înainte fiecare iterație, în prima iterație ne va fi de fapt accesarea element în matrice.lungime - 1` care evită orice probleme cu <grevă>Matrice-out-of-limite "nedefinit" elemente.De ce nu't opri iterarea înainte de index 0? Bucla se va opri iterarea când starea
i -
se evaluează la un falsey valoare (atunci când se produce 0). Trucul este că, spre deosebire de--eu
oscilanti -
operator diminuări de "i", dar dă valoare înainte de de decrementare. Consola poate demonstra acest lucru:> var i = 5; [i, eu..., am];
[5, 5, 4]
Deci, în ultima iterație, i a fost anterior 1 șii -
expresie modificări la 0 dar, de fapt, randamentele 1 (sinceră), și deci condiția trece. Pe următoarea iterației -
modificările i a -1 dar randamentele 0 (falsey), provocând execuție să renunțe imediat din partea de jos a buclei. În tradiționale înainte de buclă,i++ " și " ++i
sunt interschimbabile (ca Douglas Crockford puncte). Cu toate acestea, în marșarier pentru buclă, pentru că decrementare este, de asemenea, starea noastră de exprimare, trebuie să rămânem cui -
dacă vrem să proceseze element la indicele 0.Trivia
Unii oameni le place pentru a trage o sageata mica in reverse "pentru", buclă, și se încheie cu un cadou:
Du-te la credite WYL mi-a arătat beneficiile și ororile inversă de curent.
Unele C-stil limbi folosesc "foreach" pentru a bucla prin enumerări. În JavaScript se face cu `pentru..în structura de buclă:
Există o captură. pentru..în` va bucla prin fiecare obiect's enumerable membrii și membrii de pe prototipul său. Pentru a evita citirea valorilor care sunt moștenite prin obiect's prototipul, pur și simplu a verifica în cazul în care proprietatea aparține obiect:
În plus, ECMAScript 5 a adăugat o "forEach" metoda de a `Matrice.prototip care poate fi folosit pentru a enumera peste o matrice folosind un calback (cu polyfill este în docs astfel încât să puteți utiliza în continuare pentru browsere mai vechi):
L's important să rețineți că,
Matrice.prototip.forEach
nu't rupe atunci când callback returneaza "false". jQuery și Underscore.js furnizeze propriile lor variante pefiecare
pentru a oferi bucle care pot fi scurt-circuitat.Dacă doriți să buclă pe o matrice, utilizare standard de trei-parte "pentru" bucla.
Puteți obține unele optimizări de performanță de cache `myArray.lungimea sau iterarea peste invers.
Stiu ca e un post vechi, și există atât de multe răspunsuri mari deja. Pentru un pic mai mult de exhaustivitate m-am gândit'd arunca în altul folosind AngularJS. Desigur, aceasta se aplică numai dacă're folosind Unghiulare, evident, cu toate acestea, am'd ca a pus-o oricum.
unghiulară.forEach
are 2 argumente și, opțional, un al treilea argument. Primul argument este obiectul (matrice) pentru a itera peste, cel de-al doilea argument este funcție de iterator, și opțional al treilea argument este contextul object (de fapt menționată în interiorul buclei, ca 'asta'.Există diferite moduri de a folosi forEach buclă unghiulare. Cea mai simplă și, probabil, cel mai utilizat este
Un alt mod care este util pentru copierea de articole de la un tablou la altul este
Totuși, nu't trebuie să faci asta, pur și simplu, puteți face următoarele și-l's echivalente pentru exemplul anterior:
Acum există argumente pro și contra de a folosi
unghiulară.forEach
funcție de cum s-a construit în cu aromă de vanilie "pentru" bucla.Pro
Luați în considerare următoarele 2 bucle imbricate, care face exact același lucru. Las's spun ca am 2 tablouri de obiecte și fiecare obiect conține o serie de rezultate, fiecare dintre care are o Valoare de proprietate, care's un șir de caractere (sau orice altceva). Și să's a spus am nevoie pentru a repeta peste fiecare dintre rezultatele și dacă au're egale, atunci pentru a efectua o acțiune:
Acordate acesta este un foarte simplu exemplu ipotetic, dar am'am scris triple încorporat pentru bucle folosind cea de a doua abordare și era foarte greu de citit, și de a scrie pentru care contează.
Contra
unghiulară.forEach
, și nativ "forEach", pentru care contează, sunt atât de mult mai lent decât în mod normal "pentru" bucla....despre 90% mai lent. Deci pentru seturi mari de date, mai bine să rămânem la nativ "pentru" bucla.unghiulară.forEach
ai pune simplu un retur; declarația în funcție de caunghiulară.forEach(matrice, funcția(postul) { dacă (someConditionIsTrue) return; });
care va face ca acesta să continue din funcție pentru că iterație. Acest lucru este, de asemenea, datorită faptului că nativ "forEach" nu are suport break sau continue.Am'm sigur că nu's diverse alte argumente pro și contra, precum și, și vă rugăm să nu ezitați să adăugați orice ca tu de cuviință. Simt că, în concluzie, dacă aveți nevoie de eficiență, rămânem doar cu nativ "pentru" bucla pentru looping are nevoie. Dar, în cazul seturilor de date sunt mai mici și o eficiență este bine să dea în schimb pentru lizibilitate și writability, apoi prin toate mijloacele arunca un unghiulare.forEach în care băiatul rău.
O forEach punerea în aplicare (a[a se vedea în jsFiddle][1]):
Dacă tu nu't mintea golirea matrice:
"x" va conține ultima valoare de " y " și va fi eliminat din matrice. Puteți folosi, de asemenea,
shift()
care va oferi și elimina primul element de "y".O soluție simplă ar fi să utilizați underscore.js biblioteca. L's furnizarea de mai multe instrumente utile, cum ar fi
fiecare
si automat va delega locuri de muncă în native "forEach", dacă este disponibil.O CodePen exemplu a modului în care funcționează este:
Se vedea, de asemenea,
Matrice.prototip.forEach()
.Există trei implementări de "foreach" în jQuery, după cum urmează.
Ca Valoare de 6:
În cazul în care " de "evită ciudățenii asociat cu" în "și face să funcționeze ca "pentru" bucla de orice altă limbă, și
să
se leagaeu
în buclă spre deosebire de cadrul funcției.Acolade (
{}
) poate fi omis atunci când există doar o singură comandă (de exemplu, în exemplul de mai sus).Probabil pentru(i = 0; i < matrice.length; i++)` bucla nu este cea mai buna alegere. De ce? Dacă aveți acest lucru:
Metoda va suna din matrice[0] " cu " matrice[2]`. În primul rând, acest lucru va prima referință variabile nu't chiar trebuie, a doua nu ar avea variabile în matrice, și a treia, acest lucru va face codul mai îndrăznețe. Uite aici, l's de ce am folosit:
Și dacă vrei să fie o funcție, puteți face acest lucru:
Dacă doriți să rupă, un pic mai logica:
Exemplu:
Se întoarce:
Nu e't orice `pentru fiecare buclă în nativ JavaScript. Puteți folosi fie biblioteci pentru a obține această funcționalitate (eu recomand Underscore.js), utilizați un simplu "pentru", în buclă.
Cu toate acestea, rețineți că pot exista motive pentru a utiliza chiar și un simplu "pentru" bucla (vezi Stack Overflow întrebare Ce este cu "for...in" cu matrice repetare o idee rea?)
Acesta este un iterator pentru NON-rare listă în cazul în care indexul incepe de la 0, care este scenariul tipic atunci când se ocupă cu document.getElementsByTagName sau document.querySelectorAll)
Exemple de utilizare:
Exemplu #1
Exemplu #2
Fiecare etichetă p se
class="albastru"
Exemplu #3
Fiecare etichetă p se
class="roșu"
>Exemplu #4
Și, în sfârșit, primele 20 de albastru p categorie sunt schimbat la verde
Prudență atunci când se utilizează șir de funcții: funcția este creat out-of-context și ar trebui să fie utilizate numai în cazul în care sunteți sigur de definire variabilă. În caz contrar, mai bine să treacă funcții în cazul în care de definire a domeniului evaluării este mult mai intuitiv.
Sunt câteva modalități la bucla printr-o matrice în JavaScript, ca mai jos:
pentru - l's cel mai comun. Plin bloc de cod pentru looping
în timp ce - buclă în timp ce este o condiție prin. Se pare a fi cel mai rapid buclă
nu/în timp ce -, de asemenea, bucla printr-un bloc de cod, în timp ce condiția este adevărată, va rula cel puțin o dată
Funcțional bucle - "forEach", "harta", "filtru", de asemenea, "reduce" (acestea bucla prin funcție, dar acestea sunt utilizate în cazul în care aveți nevoie pentru a face ceva cu matrice, etc.
Pentru mai multe informații și exemple despre programare funcțională pe tablouri, uita-te la blog Funcțional programare în JavaScript: harta, se filtrează și reduce.
ECMAScript 5 (versiunea de pe JavaScript) pentru a lucra cu Tablouri:
forEach - Reiterează prin fiecare element din matrice și de a face tot ce ai nevoie cu fiecare element.
În cazul în care, mai interesat pe funcționare pe matrice folosind unele caracteristică încorporat.
harta * Se creează o nouă matrice cu rezultatul din funcția de apel invers. Această metodă este bun pentru a fi utilizate atunci când aveți nevoie pentru a formata elementele de matrice.
reducerea - după Cum spune și numele, se reduce matrice la o singură valoare de asteptare având funcția de a trece la elementul curent și rezultatul anterior de execuție.
*fiecare *** - Întoarce true sau false dacă toate elementele din matrice trece testul în funcție de apel invers.
filtru - Foarte similară cu excepția faptului că fiecare filtru returnează o matrice cu elemente care returnează adevărat anumită funcție.
Nu's nici incorporat capacitatea de a rupe în "forEach". Pentru a întrerupe executarea folosi
Matrice#unele
ca mai jos:Acest lucru funcționează pentru că "unele" întoarce cât mai curând orice de callback, executată în array comanda, returnează true, scurt-circuit executarea de restul. Original Raspuns vezi Matrice prototip pentru unele
De asemenea, am dori să adăugați acest lucru ca pe o compoziție de o buclă inversă și un răspuns de mai sus pentru cineva care ar dori această sintaxă prea.
Pro:
Beneficiul pentru acest lucru: Aveți de referință deja în primul ca't nevoie pentru a fi declarat mai târziu cu o altă linie. Acesta este la îndemână atunci când looping prin obiectul array.
Contra:
Acest lucru va rupe de referință ori de câte ori este fals - falsey (nedefinit, etc.). Acesta poate fi folosit ca un avantaj totusi. Cu toate acestea, s-ar face un pic mai greu de citit. Și, de asemenea, în funcție de browser-ul poate fi "nu" optimizat pentru a lucra mai repede decât unul original.
jQuery folosind `$.harta: