Contacte

Iterarea asupra proprietăților din obiecte. JQuery - Buclă prin matrice, obiect și elemente folosind explicit iteratorul

Funcționează așa:

// NECESITA ECMASCRIPT 2015+ var s, myStringArray = ["Bună ziua", "Lumea"]; pentru (s din myStringArray) ( // ... face ceva cu s ... )

Sau și mai bine, deoarece ECMAScript 2015 oferă și variabile bloc cu let și const:

// NECESITA ECMASCRIPT 2015+ const myStringArray = ["Bună ziua", "Lumea"]; pentru (const s din myStringArray) ( // ... face ceva cu s ... ) // s nu mai este definit aici

O notă despre tablourile rare: o matrice în JavaScript poate să nu stocheze atât de multe elemente cât este specificat în lungimea sa; acest număr raportat este pur și simplu cu unul mai mare decât cel mai mare indice la care este stocată valoarea. Dacă o matrice conține mai puține elemente decât indică lungimea sa, se spune că este rară. De exemplu, este perfect legal să existe o matrice cu elemente doar la indicii 3, 12 și 247; Lungimea unei astfel de matrice este listată ca 248, deși de fapt stochează doar 3 valori. Dacă încercați să accesați elementul la orice alt index, matricea va avea o valoare nedefinită. Deci, atunci când doriți să „iterați” o matrice, aveți o întrebare la care trebuie să răspundeți: doriți să repetați pe întregul interval specificat de lungimea sa și să procesați nedefinit pentru elementele lipsă sau doriți să procesați numai elemente prezente efectiv? Există multe aplicații pentru ambele abordări; depinde doar pentru ce folosești matricea.

Dacă iterați peste o matrice cu for .. of , corpul buclei este executat după lungime, iar variabila de control al buclei este setată la nedefinită pentru orice elemente care nu sunt de fapt în matrice. În funcție de detaliile codului dvs. „faceți ceva”, acest comportament poate fi ceea ce doriți, dar dacă nu este ceea ce doriți, ar trebui să utilizați o abordare diferită.

Desigur, unii dezvoltatori nu au de ales decât să folosească oricum o abordare diferită, deoarece din anumite motive vizează o versiune de JavaScript care nu este încă acceptată pentru... din .

Atâta timp cât implementarea dvs. JavaScript este compatibilă cu o versiune anterioară a specificației ECMAScript (care, de exemplu, exclude versiunile de Internet Explorer înainte de 9), puteți utiliza metoda iteratorului Array#forEach în loc de o buclă. În acest caz, treceți o funcție care va fi apelată pentru fiecare element din matrice:

Var myStringArray = [ "Bună ziua", "Lumea" ]; myStringArray.forEach(funcție(e) ( // ... face ceva cu s ... ));

Spre deosebire de ... din , .forEach apelează funcția doar pe elementele care conțin de fapt valori. Dacă trecem matricea noastră ipotetică cu trei elemente și o lungime de 248, aceasta va apela funcția doar de trei ori, nu de 248 de ori. De asemenea, face distincție între elementele lipsă și elementele care sunt de fapt setate la nedefinit; pentru cel din urmă, va apela în continuare funcția, trecând o valoare nedefinită ca argument. Dacă așa doriți să gestionați matricele rare, .forEach ar putea fi calea de urmat, chiar dacă traducătorul dvs. acceptă pentru ... din .

Opțiunea finală, care funcționează în toate versiunile de JavaScript, este o buclă de numărare explicită. Pur și simplu numărați de la 0 la unu mai puțin decât lungimea și utilizați contorul ca index. Bucla principală arată astfel:

Un avantaj al acestei abordări este că puteți alege cum să gestionați tablourile rare; Codul de mai sus va rula corpul buclei pe toată lungimea cu s setat la nedefinit pentru orice elemente lipsă, cum ar fi pentru .. din . Dacă, în schimb, doriți să procesați doar elementele existente ale unei matrice rare, cum ar fi .forEach , puteți adăuga o verificare simplă la index:

Var i, s, myStringArray = [ "Bună ziua", "Lumea" ], len = myStringArray.length; pentru (i=0; i

Atribuirea valorii lungimii unei variabile locale (spre deosebire de includerea expresiei myStringArray.length completă în condiția buclei) poate avea un impact semnificativ asupra performanței, deoarece omite căutarea proprietăților până la sfârșit de fiecare dată; Când folosesc Rhino pe mașina mea, viteza este de 43%.

Puteți vedea că memoria cache a lungimii se face în clauza de inițializare a buclei, astfel:

Var i, len, myStringArray = [ "Bună ziua", "Lumea" ]; pentru (len = myStringArray.length, i=0; i

Sintaxa pentru ... din menționată de alții este folosită pentru a parcurge în buclă proprietățile unui obiect; deoarece o matrice în JavaScript este doar un obiect cu nume de proprietăți numerice (și o proprietate de lungime actualizată automat), teoretic ați putea bucla matricea cu ea. Dar problema este că nu se limitează la valorile proprietăților numerice (rețineți că chiar și metodele sunt de fapt doar proprietăți a căror valoare este o închidere), și nici nu este garantat să fie repetat în ordine numerică. Prin urmare, for ... din sintaxă nu ar trebui să fie folosită pentru a bucla prin matrice.

Buna ziua! Continuăm să studiem metodele de matrice și în această lecție ne vom uita la metodele de iterare pe o matrice. Aceste metode vă permit să traversați o matrice și să efectuați anumite acțiuni asupra elementelor sale. Da, am uitat să spun că toate aceste metode nu sunt acceptate în IE 8. Deși este atât de important acum că nu sunt acceptate de acest browser, dar totuși, dacă doriți suport IE8, atunci ES5-shim vă va ajuta. Și vom continua

pentru fiecare metodă

Această metodă este folosită pentru a parcurge o matrice într-o buclă, dar îi puteți trece o funcție în care puteți efectua anumite acțiuni asupra elementelor matricei. Să ne uităm la un exemplu.

Var mas = ["Banana", "Avocado", "Morcov"]; mas.forEach(funcție(articol, i, mas) ( alert(i + ": " + element + " (matrice: " + mas + ")"); ));

Aici, în exemplu, o funcție este transmisă metodei forEach, care specifică 3 parametri:

articol- element de matrice

i— numărul elementului de matrice

mas— matricea care este procesată.

Această metodă poate fi folosită în locul unei bucle for pentru a itera printr-o matrice.

metoda de filtrare

Această metodă, ca și metoda forEach, este folosită pentru a itera printr-o matrice și i se transmite o funcție ca argument, dar vă permite să filtrați matricea și returnează o nouă matrice, care conține doar acele elemente pentru care funcția pe care o transmitem. la această metodă va reveni adevărat.

Este puțin confuz, așa că hai să ne uităm la asta cu un exemplu.

Var mas = ; var positiveNum = mas.filter(function(num) ( return num > 0; )); document.write(positiveNum); // 1,4,3

În exemplu, există o matrice cu numere și trebuie să obținem o altă matrice care să conțină numai numere pozitive din matricea originală. Pentru a face acest lucru, aplicăm metoda de filtrare la matrice și apelăm o funcție care va verifica fiecare element, adică va returna toate numerele pozitive, iar rezultatul va fi stocat într-o altă matrice, în exemplu acesta este positiveNum.

metoda hărții

Metoda map creează o altă matrice, care va consta din rezultatele apelării funcției matricei originale, dar în această funcție vor avea loc unele acțiuni asupra elementelor matricei originale și rezultatul va apărea în noua matrice așa cum este. Să ne uităm la un exemplu, altfel cred că este complet neclar.

Var mas = ; var newMas = mas.map(function(item) ( return item*item; )); // am primit o matrice cu pătrate alert(newMas); // 1,4,9

În exemplu, există o matrice inițială cu numere, i se aplică metoda hărții, în care fiecare element al matricei este înmulțit cu el însuși și rezultatul este scris într-o altă matrice. Ca rezultat, obținem o matrice cu pătratele numerelor din tabloul original.

Metode fiecare/unele

Aceste metode verifică dacă un element este prezent în matrice. Ei fac acest lucru printr-o funcție care le este transmisă ca parametru, adică dacă această funcție returnează adevărat, atunci metoda în sine va returna adevărat. Mai mult, metoda every necesită ca fiecare element să corespundă condiției funcției, iar metoda some necesită ca cel puțin o potrivire. Și, ca întotdeauna, iată un exemplu pentru tine.

Var mas = ; funcția isPositiv(num) ( return num > 0; ) if(mas.every(isPositiv)) ( document.write("Matricea conține numai numere pozitive"); ) else( document.write("Matricea conține cel puțin un număr negativ "); ) if(mas.some(isPositiv)) ( document.write ("Matricea conține cel puțin un număr pozitiv"); ) else ( document.write ("Nu există numere pozitive în matrice") ;

Luați în considerare un exemplu: avem o matrice cu numere pozitive și negative și trebuie să verificăm prezența a cel puțin unui număr negativ. Pentru a face acest lucru, folosim toate metodele. Creăm o funcție care va returna numere pozitive și apoi o transmite metodei fiecare Deoarece această metodă returnează un rezultat logic, este folosită în instrucțiunile condiționate. Fiecare metodă din exemplul nostru va returna false deoarece există numere negative în matrice, dar metoda some va returna adevărat deoarece există cel puțin un număr pozitiv în matrice.

reduce/reduceDreapta

Dacă trebuie să iterați printr-o matrice, puteți utiliza forEach, for sau for..of.

Dacă trebuie să iterați printr-o matrice și să returnați date pentru fiecare element, utilizați harta.

Metode arr.reduceȘi arr.reduceDreapta Asemănătoare cu metodele de mai sus, dar sunt puțin mai complicate. Acestea sunt folosite pentru a calcula o singură valoare pe baza întregii matrice.

Sintaxă:

Let value = arr.reduce(function(previousValue, item, index, array) ( // ... ), );

Funcția este aplicată la rândul său tuturor elementelor matricei și „transferă” rezultatul său la apelul următor.

Argumente:

  • previousValue – rezultatul apelului anterior al acestei funcții, egal cu inițiala la primul apel (dacă inițiala este trecută),
  • item – următorul element al matricei,
  • index - indicele său,
  • array – matricea în sine.

Când o funcție este apelată, rezultatul apelului acesteia asupra elementului anterior al matricei este transmis ca prim argument.

Acest lucru sună complicat, dar devine mai simplu dacă vă gândiți la primul argument ca „acumulând” rezultatul apelurilor anterioare de funcții. Când este terminat, devine rezultatul reducerii.

Această metodă este cel mai ușor de înțeles, ca întotdeauna, cu un exemplu.

Aici obținem suma tuturor elementelor matricei dintr-o singură linie:

Fie arr = ; fie rezultat = arr.reduce((suma, curent) => suma + curent, 0); alerta(rezultat); // 15

Aici am folosit cea mai comună opțiune de reducere, care folosește doar 2 argumente.

Să aruncăm o privire mai atentă la modul în care funcționează.

  1. La prima rulare, suma este inițială (ultimul argument al reducerii), care este 0, iar curentul este primul element al matricei, care este 1. Astfel, rezultatul funcției este 1.
  2. A doua oară când rulăm sum = 1, adăugăm al doilea element al matricei (2).
  3. La a treia rulare, suma = 3, la care adăugăm următorul element și așa mai departe...

Fluxul de calcul arată astfel:

Sub forma unui tabel, unde fiecare linie este un apel de funcție pe următorul element al matricei:

sumă actual rezultat
primul apel 1 1
al doilea apel 1 2 3
a treia provocare 3 3 6
a patra provocare 6 4 10
a cincea provocare 10 5 15

Aici puteți vedea clar cum rezultatul apelului anterior este trecut în primul argument al celui următor.

De asemenea, putem omite valoarea inițială:

Fie arr = ; // valoarea inițială este eliminată (nu 0 la sfârșit) let result = arr.reduce((sum, current) => sum + current); alerta(rezultat); // 15

Rezultatul este exact același! Acest lucru se datorează faptului că, în absența inițialei, primul element al matricei este luat ca prima valoare, iar căutarea începe de la a doua.

Tabelul de calcul va fi același minus prima linie.

Dar o astfel de utilizare necesită precauție extremă. Dacă matricea este goală, apelarea reduce fără o valoare inițială va genera o eroare.

Iată un exemplu:

Fie arr = ; // Eroare: Reducerea matricei goale fără valoare inițială // dacă a existat o valoare inițială, reducere o va returna pentru o matrice goală. arr.reduce((suma, curent) => suma + curent);

Rezultate

Deci, pentru a rezuma, ne-am uitat la diferite metode de lucru cu tablouri într-o buclă. Toate aceste metode au un lucru în comun, și anume că toate trebuie să transmită o funcție ca argument.

  • forEach – pentru trecerea în buclă printr-o matrice.
  • filter – pentru a filtra matricea. Returnează o nouă matrice filtrată
  • every/some – pentru a verifica matricea pentru prezența elementelor individuale.
  • map - pentru a converti o matrice într-o matrice. Returnează tabloul original convertit.
  • reduce/reduceRight - Calculează o valoare din întregul tablou, apelând o funcție pe fiecare element și trecând rezultatul intermediar între apeluri. Poate fi folosit pentru a calcula suma elementelor matricei.

Sarcini

Obțineți o nouă matrice

Lăsați matricea var mas = ["HTML", "CSS", "JavaScript", "Pascal"] să fie dată, trebuie să utilizați metoda map pentru a obține o nouă matrice care va conține lungimile fiecărui element din tabloul original .

Filtrați matricea

Există o matrice var mas = trebuie să utilizați metoda de filtru pentru a obține o matrice care conține numai numere pozitive.

Verificați matricea

Există o matrice var mas = trebuie să verificați dacă există numere negative în matrice și să afișați rezultatul pe ecran.

Ei bine, în concluzie, un scurt videoclip despre metodele de buclă printr-o matrice.

  • Traducere
  • I. Iterarea peste matrice reale
    1. pentruFiecare metodă și metode aferente
    2. pentru buclă
    3. Utilizarea corectă a buclei for...in
    4. for...of loop (utilizarea implicită a iteratorului)
    5. Utilizarea explicită a iteratorului
    1. Folosind metode de iterare peste matrice reale
    2. Convertiți într-o matrice reală
    3. O notă despre obiectele runtime

I. Iterarea peste matrice reale

În acest moment, există trei moduri de a itera elementele unei matrice reale:
  1. metoda Array.prototype.forEach ;
  2. clasic pentru buclă
  3. un „corect” construit pentru... în buclă.
În plus, în curând, odată cu apariția noului standard ECMAScript 6 (ES 6), sunt așteptate încă două metode:
  1. for...of loop (utilizarea implicită a iteratorului);
  2. utilizarea explicită a iteratorului.

1. Metoda forEach și metodele conexe

Dacă proiectul dvs. este proiectat să suporte caracteristicile standardului ECMAScript 5 (ES5), puteți utiliza una dintre inovațiile acestuia - metoda forEach.

Exemplu de utilizare:
var a = ["a", "b", "c"]; a.forEach(funcție(intrare) ( console.log(intrare); ));
În general, utilizarea forEach necesită conectarea bibliotecii de emulare es5-shim pentru browserele care nu acceptă nativ această metodă. Acestea includ IE 8 și versiuni anterioare, care sunt încă utilizate în unele locuri.

Avantajul forEach este că nu este nevoie să declarați variabile locale pentru a stoca indexul și valoarea elementului de matrice curent, deoarece acestea sunt transmise automat funcției de apel invers ca argumente.

Dacă sunteți îngrijorat de costul posibil al apelării unui apel invers pentru fiecare element, nu vă faceți griji și citiți asta.

ForEach este proiectat să itereze prin toate elementele unei matrice, dar pe lângă aceasta, ES5 oferă mai multe metode utile pentru a itera prin toate sau unele elemente plus efectuarea unor acțiuni asupra acestora:

  • fiecare - returnează adevărat dacă pentru fiecare element al matricei apelul returnează o valoare care poate fi convertită în adevărat .
  • some - returnează adevărat dacă pentru cel puțin un element al matricei, callback returnează o valoare care poate fi convertită în adevărat.
  • filter - creează o nouă matrice care include acele elemente ale matricei originale pentru care callback returnează true .
  • hartă - creează o nouă matrice constând din valorile returnate de apel invers.
  • reduce - reduce o matrice la o singură valoare, aplicând un callback fiecărui element al matricei pe rând, începând cu primul (poate fi util pentru calcularea sumei elementelor matricei și a altor funcții rezumative).
  • reduceRight - funcționează similar cu reduce, dar iterează prin elemente în ordine inversă.

2. Pentru buclă

Bine vechi pentru reguli:

Var a = ["a", "b", "c"]; indicele var; pentru (index = 0; index< a.length; ++index) { console.log(a); }
Dacă lungimea matricei este constantă pe tot parcursul buclei și bucla în sine aparține unei secțiuni de cod critice pentru performanță (ceea ce este puțin probabil), atunci puteți utiliza o versiune „mai optimă” a pentru care stochează lungimea matricei. :

Var a = ["a", "b", "c"]; var index, len; pentru (index = 0, len = a.lungime; index< len; ++index) { console.log(a); }
În teorie, acest cod ar trebui să ruleze puțin mai repede decât cel anterior.

Dacă ordinea elementelor nu este importantă, atunci puteți merge și mai departe în ceea ce privește optimizarea și puteți scăpa de variabila pentru stocarea lungimii matricei, schimbând ordinea căutării în sens invers:

Var a = ["a", "b", "c"]; indicele var; pentru (index = a.length - 1; index >= 0; --index) ( console.log(a); )
Cu toate acestea, în motoarele JavaScript moderne, astfel de jocuri de optimizare nu înseamnă de obicei nimic.

3. Utilizarea corectă a buclei for...in

Dacă vi se recomandă să utilizați o buclă for...in, amintiți-vă că iterarea peste matrice nu este scopul pentru care este destinată. Contrar unei concepții greșite obișnuite, bucla for...in nu iterează peste indici de matrice, ci mai degrabă prin proprietăți enumerabile ale unui obiect.

Cu toate acestea, în unele cazuri, cum ar fi iterarea peste matrice rare, pentru...in poate fi utilă, atâta timp cât luați măsuri de precauție, așa cum se arată în exemplul de mai jos:

// a - tablou rar var a = ; a = „a”; a = „b”; a = "c"; pentru (cheie var în a) ( if (a.hasOwnProperty(cheie) && /^0$|^\d*$/.test(cheie) && cheie<= 4294967294) { console.log(a); } }
În acest exemplu, sunt efectuate două verificări la fiecare iterație a buclei:

  1. că matricea are propria sa proprietate numită cheie (nu este moștenită de la prototipul său).
  2. acea cheie este un șir care conține reprezentarea zecimală a unui număr întreg a cărui valoare este mai mică decât 4294967294 . De unde vine ultimul număr? Din definiția unui index de matrice din ES5, care arată că cel mai mare indice pe care îl poate avea un element dintr-o matrice este: (2^32 - 2) = 4294967294 .
Desigur, astfel de verificări vor dura mai mult timp la executarea buclei. Dar în cazul unei matrice rare, această metodă este mai eficientă decât o buclă for, deoarece în acest caz sunt iterate doar acele elemente care sunt definite în mod explicit în matrice. Deci, în exemplul de mai sus, vor fi efectuate doar 3 iterații (pentru indicii 0, 10 și 10000) - față de 10001 în bucla for.

Pentru a nu scrie un cod de verificare atât de greoi de fiecare dată când trebuie să iterați printr-o matrice, îl puteți scrie ca o funcție separată:

Funcția arrayHasOwnIndex(matrice, cheie) ( returnează matrice.hasOwnProperty(cheie) && /^0$|^\d*$/.test(cheie) && cheie<= 4294967294; }
Apoi corpul buclei din exemplu va fi redus semnificativ:

Pentru (tastați a) ( dacă (arrayHasOwnIndex(a, cheie)) ( console.log(a); ) )
Codul de verificare discutat mai sus este universal, potrivit pentru toate cazurile. Dar, în schimb, puteți utiliza o versiune mai scurtă, deși formal nu este complet corectă, dar totuși potrivită pentru majoritatea cazurilor:

Pentru (tastați a) ( dacă (a.hasOwnProperty(cheie) && String(parseInt(key, 10)) === cheie) ( console.log(a); ) )

4. For...of loop (utilizarea implicită a iteratorului)

ES6, încă în stare de schiță, ar trebui să introducă iteratori în JavaScript.

Iterator este un protocol implementat de un obiect care definește o modalitate standard de a obține o secvență de valori (finită sau infinită).
Un iterator este un obiect care definește o metodă next() - o funcție fără argument care returnează un obiect cu două proprietăți:

  1. done (boolean) - adevărat dacă iteratorul a ajuns la sfârșitul secvenței iterabile. În caz contrar, valoarea este falsă.
  2. valoare - definește valoarea returnată de iterator. Poate fi nedefinit (lipsește) dacă proprietatea realizată este adevărată.
Multe obiecte încorporate, incl. tablourile reale au iteratoare în mod implicit. Cea mai simplă modalitate de a folosi un iterator pe tablouri reale este să folosiți noul for...of construct.

Exemplu de utilizare pentru...de:

Varval; var a = ["a", "b", "c"]; pentru (val of a) ( console.log(val); )
În exemplul de mai sus, bucla for...of apelează implicit iteratorul obiectului Array pentru a obține fiecare valoare a matricei.

5. Utilizarea explicită a iteratorului

Iteratorii pot fi, de asemenea, folosiți în mod explicit, totuși, în acest caz, codul devine mult mai complicat în comparație cu bucla for...of. Arata cam asa:

Var a = ["a", "b", "c"]; var it = a.entries(); intrare var; în timp ce (!(entry = it.next()). done) ( console.log(entry.value); )
În acest exemplu, metoda Array.prototype.entries returnează un iterator care este utilizat pentru a afișa valorile matricei. La fiecare iterație, entry.value conține o matrice de forma [cheie, valoare] .

II. Iterarea peste obiecte asemănătoare matricei

Pe lângă matricele reale, în JavaScript există și obiecte asemănătoare matricei . Ceea ce au în comun cu tablourile reale este că au o proprietate de lungime și proprietăți numite ca numere corespunzătoare elementelor matricei. Exemplele includ colecția DOM NodeList și argumentele pseudo-matrice disponibile în orice funcție/metodă.

1. Folosirea metodelor de iterare peste matrice reale

Cel puțin, majoritatea, dacă nu toate, metodele de iterare peste matrice reale pot fi folosite pentru a repeta peste obiecte asemănătoare matricei.

Construcțiile for și for...in pot fi aplicate obiectelor asemănătoare matrice exact în același mod ca și matricelor reale.

Metodele ForEach și alte Array.prototype se aplică și obiectelor asemănătoare matricei. Pentru a face acest lucru, trebuie să utilizați Function.call sau Function.apply .

De exemplu, dacă doriți să aplicați forEach la proprietatea childNodes a unui obiect Node, ați proceda astfel:

Array.prototype.forEach.call(node.childNodes, function(child) ( // face ceva cu obiectul copil));
Pentru a face acest truc mai ușor de reutilizat, puteți declara o referință la metoda Array.prototype.forEach într-o variabilă separată și o puteți utiliza ca scurtătură:

// (Presupunând că tot codul de mai jos este în același domeniu) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // face ceva cu obiectul copil));
Dacă un obiect asemănător matricei are un iterator, acesta poate fi utilizat în mod explicit sau implicit pentru a itera asupra obiectului în același mod ca și pentru matricele reale.

2. Convertiți într-o matrice reală

Există, de asemenea, o altă modalitate, foarte simplă, de a repeta peste un obiect asemănător matricei: convertiți-l într-o matrice reală și utilizați oricare dintre metodele discutate mai sus pentru a repeta peste matrice reale. Pentru conversie, puteți utiliza metoda generică Array.prototype.slice, care poate fi aplicată oricărui obiect asemănător matricei. Acest lucru se face foarte simplu, așa cum se arată în exemplul de mai jos:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
De exemplu, dacă doriți să convertiți o colecție NodeList într-o matrice reală, veți avea nevoie de cod de genul acesta:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);
Actualizați: După cum s-a menționat în comentarii

12 martie 2016

În JavaScript modern, există așa-numitele „metode de iterație” care sunt folosite pentru a itera prin matrice. În acest tutorial vom acoperi următoarele metode:

pentru fiecare

Metoda .forEach() este folosită pentru căutare matrice. Apelează așa-numita funcție de apel invers, cu ajutorul căreia sunt trecuți trei parametri item, i, arr, unde:

  • item — element de matrice;
  • i este numărul de serie al matricei;
  • arr este matricea în sine care ar trebui repetată.

Pentru a înțelege mai ușor cum să utilizați această metodă, luați în considerare un exemplu:

Var user="admin","pass",31]; user.forEach(function(element,i,user)( alert("Valoarea articolului nr. " + i + " : " + element); ));

Această metodă poate fi folosită în locul unei bucle for obișnuite.

filtru

Metoda .filter() este folosită pentru filtrare, folosește și funcția de apel invers, dar creează o nouă matrice dacă elementele din matrice se potrivesc cu valoarea true:

Var arr=; var newArr=arr.filter(function(number)( return number< 0; }); alert(newArr); // выведет -34,-4

În acest exemplu, numerele sunt verificate pentru valori negative, iar rezultatul este o nouă matrice cu aceste valori. Puteți veni cu propriile condiții; acestea nu trebuie să fie neapărat numere.

fiecare/unii

Aceste două metode sunt similare una cu cealaltă și ambele sunt folosite pentru a verifica o matrice, doar metoda .fiecare() returnează adevărat dacă toate valorile din matrice se potrivesc cu condiția specificată și cu metoda .niste() returnează adevărat dacă cel puțin o valoare corespunde condiției:

Var arr=; alert(arr.every(function(number)( return number< 0; })); // выведет false

Sper să fie clar că dacă în exemplul de mai sus am folosit vreo metodă atunci am fi afișat valoarea true în loc de false.

Hartă

Metoda .map() transformă matricea și obține una nouă din aceasta. Totul se face apelând funcția de apel invers:

Var arr=; var newArr=arr.map(function(number)( return number*2; )); alert(newArr);

În acest exemplu, am primit o nouă matrice cu valori duble ale elementelor.

reduce/reduceDreapta

Ultimele metode pe care le vom analiza sunt reduce și reduceRight. Sunt folosite pentru a procesa fiecare element al matricei în timp ce salvează rezultatul intermediar. Metoda iterează prin fiecare element de la stânga la dreapta, reduceRight face opusul. Spre deosebire de alte metode, pe lângă funcția de apel invers, aici este specificat și argumentul initialValue - „valoare inițială”. În plus, funcția de apel invers specifică „rezultatul intermediar” - valoarea precedentăȘi currentItem— elementul curent al matricei.

Să ne uităm la un exemplu:

Funcția getSums(arr) ( var rezultat = ; if (!arr.length) returnează rezultatul; var totalSum = arr.reduceRight(function(sum, item) (rezultat.push(sum); return sum + item; )); rezultat .push(totalSum returnează rezultatul(getSums()); // 1,3,6,10,15

Ce s-a întâmplat în acest exemplu? Am creat o funcție care ne permite să obținem o nouă matrice cu elemente create din suma celor anterioare. Mai mult, raportul elementelor vine de la final. Și iată un exemplu mai simplu în care am creat o funcție care calculează suma elementelor dintr-o matrice:

Funcția getSum(arr) ( var rezultat = arr.reduce(funcție(sumă, curent) ( returnează suma + curent )); returnează rezultat; ); alert(getSum()); Etichete:

22 de răspunsuri

După rularea acestui test cu majoritatea browserelor moderne...

În prezent cea mai rapidă formă de buclă (și, după părerea mea, cea mai evidentă din punct de vedere sintactic).

standard pentru bucla de lungime cache

Pentru (var i = 0, len = myArray.length; i< len; i++) { }

Aș spune că acesta este cu siguranță un caz în care aplaud dezvoltatorii de motoare JavaScript. Timpul de execuție ar trebui optimizat pentru claritate, nu pentru comoditate.

Din iunie 2016, mai multe teste în cel mai recent Chrome (71% din piața browserelor în mai 2016 și în creștere):

  • Cel mai rapid ciclu este ciclul buclă, atât cu cât și fără lungime cache, oferind performanțe foarte similare. (O buclă for cu o lungime în cache produce uneori rezultate mai bune decât una care nu este memorată în cache, dar diferența este aproape neglijabilă, ceea ce înseamnă că motorul poate fi optimizat în favoarea buclei standard și poate cea mai simplă fără cache).
  • Bucla while cu scăderi a fost de aproximativ 1,5 ori mai lentă decât bucla for.
  • O buclă care folosește o funcție de apel invers (de exemplu, standard forEach) a fost de aproximativ 10 ori mai lentă decât o buclă for.

Cred că acest fir este prea vechi și programatorii simt că trebuie să memoreze lungimea în cache sau să folosească intersecții cu scădere în spate pentru a obține performanțe mai bune, scriind cod mai puțin pretențios și mai predispus la erori decât o simplă buclă for. De aceea recomand:

    Dacă aplicația dvs. iterează printr-o mulțime de elemente sau codul dvs. de buclă se află într-o funcție care este utilizată frecvent, o buclă dreaptă este răspunsul:

    Pentru (var i = 0; i< arr.length; i++) { // Do stuff with arr[i] or i }

    Dacă aplicația dvs. nu repetă cu adevărat peste o mulțime de elemente sau trebuie doar să faceți mici iterații ici și colo, utilizarea standardului forEach callback sau orice funcție similară din biblioteca dvs. JS aleasă poate fi mai curată și mai puțin predispusă la erori, deoarece indexul domeniul de aplicare al variabilei este privat și nu este nevoie să folosiți paranteze care accesează direct valoarea matricei:

    Arr.forEach(funcție(valoare, index) ( // Faceți lucruri cu valoare sau index ));

    Dacă într-adevăr trebuie să amestecați câteva milisecunde în timp ce repetați peste miliarde de rânduri, iar lungimea matricei nu se va schimba în acest proces, ați putea lua în considerare stocarea în cache a lungimii într-o buclă for. Deși cred că chiar nu este necesar în zilele noastre:

    Pentru (var i = 0, len = arr.length; i< len; i++) { // Do stuff with arr[i] }

Este doar 2018, așa că o actualizare ar putea fi bună...

Și chiar ar trebui nu sunt de acord cu răspunsul acceptat. Depinde de diferite browsere. unii fac forEach mai repede, alții for-loop și alții while testează toate metodele http://jsben.ch/mW36e

Arr.forEach(a => ( // ... )

și din moment ce puteți vedea o mulțime de bucle for(a = 0;...) precum for(a = 0;...) merită menționat că fără variabile „var” va fi definit global și acest lucru poate avea un impact semnificativ viteza, deci va fi lent.

var arr = arr = new Array(11111111).fill(255); var bancuri = [ [ „gol”, () =>< l; a++); }] , ["for-loop", () =>( for(var a = 0, l = arr.length; a< l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () =>( for(var a = 0, l = arr.length; a< l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () =>( for(var a = 0; a< arr.length; ++a) var b = arr[a] + 1; }] , ["reverse for-loop", () =>( for(var a = arr.length - 1; a >= 0; --a) var b = arr[a] + 1; )] ,["while-loop", () => ( var a = 0 , l = arr.length;< l) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () =>( var a = lungime.arr. - 1; // ATENTIE do ( var b = arr[a] + 1; ) while(a--); )] , ["forEach", () => ( arr.forEach( a => ( var b = a + 1; )); ["for..in (doar 3,3%)", () => ( var ar = arr.slice(0,arr.length/33) ; for( const a in ar) ( var b = a + 1; )] , ["Duff device", () => ( var i = 0; var r = arr.length % 8; var n = (arr .length - r) ) / 8; if (r > 0) do ( var b = arr + 1; ) în timp ce (--r) dacă (n > 0) do ( var b = arr[i] + 1; var c = arr +). 1; var e = arr + 1; var g = arr + 1; % 8; var n = (arr.length-r) ///Math.floor(arr.length // var i = arr.length ; arr[--i] + 1; --r) în timp ce (n)( var b = arr[i] + 1; var c = arr + 1; var d = arr + 1; var e = arr + 1; var f = arr + 1 var g = arr + 1; function bench(title, f) ( var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log("$(title) a luat $(t1-t0 ) msec"); ) var globalVarTime = bench("for-loop fără "var"", () => ( // Aici dacă uitați să puneți "var", astfel încât variabilele" vor fi globale pentru (a = 0, l = lungimea arr.;< l; ++a) var b = arr[a] + 1; }); var times = benches.map(function(a) { arr = new Array(11111111).fill(255); return }).sort((a,b) =>a-b); var max = ori; ori = ori.map(a => (a = (a/max)*100; return a; )); var template = (titlu, ora, n) => "

" + "$(titlu) " + " $(Număr(time.toFixed(3)))msec" + "
"; var strRes = times.map(t => template(...t)).join("\n") + "

for-loop fără „var” $(globalVarTime) msec."; var $container = document.getElementById("container"); $container.innerHTML = strRes; body (color:#fff; background:#333; font-family :helvetica; ) body > div > div ( clear:both ) body > div > div > span ( float:left; width:43%; margin:3px 0; text-align:right; ) body > div > div > span :nth-child(2) ( text-align:left; background:darkorange; animation:showup .37s .111s; -webkit-animation:showup .37s .111s; ) @keyframes showup ( de la ( lățime: 0; ) ) Afișare @-webkit-keyframes (de la ( lățime: 0; ) )

2014 În timp ce în urmă

Gândește logic.

Uita-te la asta

For(var index = 0 , length = array.length ; index< length ; index++) { //do stuff }

  • Trebuie să creați cel puțin 2 variabile (index, lungime)
  • Trebuie să verificați dacă indicatorul de lungime este mai mic de
  • Indicele trebuie crescut
  • bucla for are 3 parametri

Acum spune-mi de ce ar trebui să fie mai rapid decât:

Var lungime = array.length; while(--lungime) ( //sau lungime-- //face lucruri )

  • O variabilă
  • Fără verificări
  • indicele scade (mașinile preferă acest lucru)
  • While are un singur parametru

Am fost complet confuz când Chrome 28 a arătat că bucla for a fost mai rapidă decât timpul. Ar trebui să fie ceva de genul

„Ei bine, toată lumea folosește o buclă for, să ne concentrăm pe asta când pentru Chrome.”

Dar acum, în 2014, bucla while revine la Chrome. este de 2 ori mai rapid, în alte/vechi browsere a fost întotdeauna mai rapid.

Am făcut câteva teste noi în ultima vreme. Acum, în lumea reală a utilizării, aceste coduri scurte nu au valoare și jsperf nu poate executa corect bucla while, deoarece trebuie să recreeze array.length, ceea ce necesită și timp.

NU POATE obține viteza reală a buclei while pe jsperf.

trebuie să vă creați propria funcție și să verificați asta folosind window.performance.now()

Și da... nu există nicio modalitate pentru o buclă de timp să fie mai rapidă.

Problema reală este timpul real de manipulare/redare/timpul de desen sau cum vrei să-i spui.

De exemplu, am o scenă de pânză în care trebuie să calculez coordonatele și coliziunile... acest lucru se face între 10-200 MicroSecunde (nu milisecunde). este nevoie de mai multe milisecunde pentru a face totul. La fel ca în DOM.

Există o altă modalitate super eficientă de a folosi bucla în unele cazuri... de exemplu pentru a copia/clona o matrice

For(var i = array.length; i > 0; arrayCopy[ --i ] = array[ i ] // fac lucruri);

Vă rugăm să rețineți setările parametrilor:

  • La fel ca în bucla while. Folosesc o singură variabilă
  • Este necesar să se verifice dacă indicele este mai mare decât 0;
  • După cum puteți vedea, această abordare este diferită de bucla obișnuită pe care o folosește toată lumea, deoarece fac lucruri în interiorul celui de-al 3-lea parametru și, de asemenea, scad direct în interiorul matricei.

Se spune că acest lucru confirmă faptul că mașini precum

am scris că m-am gândit să o fac puțin mai scurtă și să elimin câteva lucruri inutile și am scris-o pe aceasta folosind același stil:

For(var i = array.length ; i-- ; arrayCopy[ i ] = array[ i ] // fac lucruri);

Chiar dacă este mai scurt, se pare că folosirea i încetinește din nou totul. Aceasta este cu 1/5 mai lent decât bucla anterioară for și while.

Notă:; foarte important după pentru looo fără ()

Chiar dacă tocmai v-am spus că jsperf nu este cel mai bun mod de a testa scripturile. Am adăugat 2 bucle aici.

Și iată un alt răspuns despre performanță în javascript

Acest răspuns ar trebui să arate modalități performante de a scrie javascript. Deci, dacă nu poți citi asta, întreabă și vei primi un răspuns sau vei citi o carte despre javascript http://www.ecma-international.org/ecma-262/5.1/

Cea mai recentă revizuire a testului pe care l-am pregătit (prin reutilizarea unuia mai vechi) arată un lucru.

Lungimea memoriei cache nu este atât de importantă, dar nu doare.

Fiecare primă rulare a testului de mai sus (în fila nou deschisă) oferă cele mai bune rezultate pentru ultimele 4 fragmente (al treilea, al cincilea, al 7-lea și al 10-lea în topuri) în Chrome, Opera și Firefox pe Debian Squeeze pe 64 de biți ( hardware-ul meu desktop). Execuțiile ulterioare dau un rezultat complet diferit.

Concluziile performanței sunt simple:

  • Intrați într-o buclă for (înainte) și verificați cu !== în schimb< .
  • Dacă nu trebuie să reutilizați matricea mai târziu, atunci este eficientă și o buclă cu lungime redusă și shift() matrice distructivă.

În prezent (2011.10) șablonul de mai jos pare a fi cel mai rapid.

Pentru (var i = 0, len = arr.length; i !== len; i++) ( ... )

Amintiți-vă că stocarea în cache arr.length nu este critică aici, așa că puteți doar să testați i !== arr.length și nu va fi nicio atingere de performanță, dar veți obține un cod mai scurt.

PS: Știu că într-un fragment cu shift() rezultatul său poate fi folosit în loc de a accesa elementul 0, dar am trecut cumva cu vederea asta după ce am reutilizat revizuirea anterioară (care avea valoarea greșită în timpul buclelor), iar mai târziu nu am vrut să piardă rezultatele deja obținute.

„Cel mai bun” ca în performanță pură? sau performanță ȘI?

Cea mai bună performanță pură este cea care utilizează cache-ul și operatorul de prefix ++ (datele mele: http://jsperf.com/caching-array-length/189)

Pentru (var i = 0, len = myArray.length; i< len; ++i) { // blah blah }

Aș spune că o buclă fără cache este cel mai bun echilibru între timpul de execuție și timpul de citire al programatorului. Fiecare programator care începe cu C/C++/Java nu va cheltui ms pentru a citi acest lucru

Pentru(var i=0; i< arr.length; i++){ // blah blah }

** stocați în cache lungimea matricei în interiorul buclei, câteva secunde de timp vor scăpa. Depinde de elementele din matrice, dacă există mai multe elemente în matrice, există o mare diferență în ceea ce privește timpul Ms*

SARr; //Matrice; for(var i = 0; i

SARr; //Matrice; for(var i = 0,len = sArr.length ; i< len ; i++) { callArray(sArr[i]); //function call } ***end: 1.354ms***

Acesta este anul 2017 .

Am facut niste teste.

Se pare că metoda while este cea mai rapidă din Chrome.

Se pare că decrementul din stânga (--i) este mult mai rapid decât celelalte (++i , i-- , i++) în Firefox.

Această abordare este în medie de post. Dar repetă matricea în ordine inversă.

Fie i = array.lungime; în timp ce (--i >= 0) ( face Ceva (matrice[i]); )

Dacă ordinea de prioritate este importantă, utilizați această abordare.

Fie ii = array.length; fie i = 0; in timp ce eu< ii) { doSomething(array[i]); ++i; }

Eu scriu mereu în primul stil.

Chiar dacă compilatorul este suficient de inteligent pentru a-l optimiza pentru matrice, dar este totuși inteligent dacă folosim DOMNodeList aici sau un obiect complex cu lungime calculată?

Știu că întrebarea este despre matrice, dar cred că este o practică bună să scrieți toate buclele în același stil.

Var arr = ; // Tabloul var i = 0; in timp ce eu< arr.length) { // Do something with arr[i] i++; }

i++ este mai rapid decât ++i, --i și i -



Ți-a plăcut articolul? Împărtășește-l