Js repetă peste toate elementele. Matrice: Metode de iterare. Convertiți într-o matrice reală

  • I. Iterarea peste matrice reale
  • pentruFiecare metodă și metode aferente
  • pentru buclă
  • Utilizarea corectă a buclei for...in
  • for...of loop (utilizarea implicită a iteratorului)
  • Utilizarea explicită a iteratorului
  • II. Iterarea peste obiecte asemănătoare matricei
  • Folosind metode de iterare peste matrice reale
  • Convertiți într-o matrice reală
  • O notă despre obiectele runtime
I. Iterarea peste matrice reale

În acest moment, există trei moduri de a itera elementele unui tablou real:

  • metoda Array.prototype.forEach ;
  • clasic pentru buclă
  • 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:

  • for...of loop (utilizarea implicită a iteratorului);
  • 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 browsere 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 în plus față de acesta, ES5 oferă mai multe metode utile pentru a itera 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 de matrice 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, iar bucla în sine aparține unei secțiuni critice pentru performanță a codului (ceea ce este puțin probabil), atunci puteți utiliza o versiune „mai optimă” a pentru care stochează lungimea matrice:

    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) ( dacă (a.hasOwnProperty(cheie) && /^0$|^d*$/.test(cheie) && cheie< 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; while(a< 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.harta(a => (a = (a/max)*100; return a; )); var template = (titlu, ora, n) => "" + "$(titlu) " + " $(Number(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șarea @-webkit-keyframes (de la ( lățime: 0; ) )

    2014 În timp ce în urmă

    Gândește logic.

    Uită-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/timp 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ă -ing.

    Î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 al 0-lea element, 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 făcut-o. doresc să piardă rezultatele deja obținute.

    „Cel mai bun” ca în performanță pură? sau performanta SI?

    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 = 0) ( face Something(array[i]); )

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

    Fie ii = array.length; fie i = 0; în timp ce (i< 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; în timp ce (i< arr.length) { // Do something with arr[i] i++; }

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

    • Traducere
    • I. Iterarea peste matrice reale
    • pentruFiecare metodă și metode aferente
    • pentru buclă
    • Utilizarea corectă a buclei for...in
    • for...of loop (utilizarea implicită a iteratorului)
    • Utilizarea explicită a iteratorului
    • Folosind metode de iterare peste matrice reale
    • Convertiți într-o matrice reală
    • O notă despre obiectele runtime
    I. Iterarea peste matrice reale În acest moment, există trei moduri de a repeta peste elementele unui tablou real:
  • metoda Array.prototype.forEach ;
  • clasic pentru buclă
  • 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:
  • for...of loop (utilizarea implicită a iteratorului);
  • utilizarea explicită a iteratorului.
  • 1. Metoda forEach și metodele aferente Dacă proiectul dumneavoastră 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 browsere 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 peste toate elementele unei matrice, dar în plus față de acesta, ES5 oferă mai multe metode utile pentru a itera 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 de matrice 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, iar bucla în sine aparține unei secțiuni critice pentru performanță a codului (ceea ce este puțin probabil), atunci puteți utiliza o versiune „mai optimă” a pentru care stochează lungimea matrice:

    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 unei bucle 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) ( dacă (a.hasOwnProperty(cheie) && /^0$|^\d*$/.test(cheie) && cheie

    • HTML
    • JavaScript
    $("ul#myList").children().each(function())( console.log($(this).text()); )); // Rezultat: // HTML // CSS // JavaScript

    Să ne uităm la o modalitate de a determina ultimul index (articol) în fiecare metodă a jQuery.

    // selectează elemente var myList = $("ul li"); // determina numarul de elemente din selectie var total = myList.length; // iterează prin elementele selectate myList.each(function(index) ( if (index === total - 1) ( // acesta este ultimul element din selecție ) ));

    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 forta bruta 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.

    filtra

    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 .unele() returnează adevărat dacă cel puțin o valoare corespunde condiției:

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

    Sper că este clar că dacă metoda some ar fi fost folosită în exemplul de mai sus, 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 de elemente dublate.

    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” - previousValue ș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(function(sum, current) ( returne suma + curent )); returnează rezultat; ); alert(getSum());